diff --git a/app/vendor/cakephp-plugins.php b/app/vendor/cakephp-plugins.php
index 2a207981b..7520a9c95 100644
--- a/app/vendor/cakephp-plugins.php
+++ b/app/vendor/cakephp-plugins.php
@@ -14,6 +14,7 @@
'EnvSource' => $baseDir . '/plugins/EnvSource/',
'Migrations' => $baseDir . '/vendor/cakephp/migrations/',
'OrcidSource' => $baseDir . '/plugins/OrcidSource/',
+ 'SshKeyAuthenticator' => $baseDir . '/plugins/SshKeyAuthenticator/',
'TestWidget' => $baseDir . '/plugins/TestWidget/',
],
];
diff --git a/app/vendor/cakephp/cakephp-codesniffer/.github/workflows/ci.yml b/app/vendor/cakephp/cakephp-codesniffer/.github/workflows/ci.yml
index 92cbce0f7..29190d14d 100644
--- a/app/vendor/cakephp/cakephp-codesniffer/.github/workflows/ci.yml
+++ b/app/vendor/cakephp/cakephp-codesniffer/.github/workflows/ci.yml
@@ -14,11 +14,13 @@ jobs:
strategy:
fail-fast: false
matrix:
- php-version: ['7.2', '7.4', '8.0']
- prefer-lowest: ['']
+ php-version: ['7.2', '7.4']
+ dependencies: [highest]
include:
- php-version: '7.2'
- prefer-lowest: 'prefer-lowest'
+ dependencies: 'lowest'
+ - php-version: '8.0'
+ composer-options: "--ignore-platform-reqs"
steps:
- uses: actions/checkout@v2
@@ -30,29 +32,11 @@ jobs:
extensions: mbstring, intl
coverage: pcov
- - name: Get composer cache directory
- id: composer-cache
- run: echo "::set-output name=dir::$(composer config cache-files-dir)"
-
- - name: Get date part for cache key
- id: key-date
- run: echo "::set-output name=date::$(date +'%Y-%m')"
-
- - name: Cache composer dependencies
- uses: actions/cache@v1
+ - name: Composer install
+ uses: ramsey/composer-install@v3
with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }}
-
- - name: Composer Install
- run: |
- if [[ ${{ matrix.php-version }} == '8.0' ]]; then
- composer install --ignore-platform-reqs
- elif ${{ matrix.prefer-lowest == 'prefer-lowest' }}; then
- composer update --prefer-lowest --prefer-stable
- else
- composer install
- fi
+ dependency-versions: ${{ matrix.dependencies }}
+ composer-options: "${{ matrix.composer-options }}"
- name: Setup problem matchers for PHPUnit
if: matrix.php-version == '7.4'
@@ -82,22 +66,8 @@ jobs:
tools: cs2pr
coverage: none
- - name: Get composer cache directory
- id: composer-cache
- run: echo "::set-output name=dir::$(composer config cache-files-dir)"
-
- - name: Get date part for cache key
- id: key-date
- run: echo "::set-output name=date::$(date +'%Y-%m')"
-
- - name: Cache composer dependencies
- uses: actions/cache@v1
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }}
-
- name: Composer install
- run: composer install
+ uses: ramsey/composer-install@v3
- name: Run PHP CodeSniffer
run: vendor/bin/phpcs --report=checkstyle CakePHP/ | cs2pr
diff --git a/app/vendor/cakephp/cakephp-codesniffer/CakePHP/Sniffs/Classes/ReturnTypeHintSniff.php b/app/vendor/cakephp/cakephp-codesniffer/CakePHP/Sniffs/Classes/ReturnTypeHintSniff.php
index 9f1764cab..699115c5a 100644
--- a/app/vendor/cakephp/cakephp-codesniffer/CakePHP/Sniffs/Classes/ReturnTypeHintSniff.php
+++ b/app/vendor/cakephp/cakephp-codesniffer/CakePHP/Sniffs/Classes/ReturnTypeHintSniff.php
@@ -230,7 +230,7 @@ protected function getClassNameWithNamespace(File $phpCsFile): ?string
return ClassHelper::getFullyQualifiedName(
$phpCsFile,
- $phpCsFile->findPrevious(TokenHelper::$typeKeywordTokenCodes, $lastToken)
+ $phpCsFile->findPrevious([T_CLASS, T_TRAIT, T_INTERFACE, T_ENUM], $lastToken)
);
}
}
diff --git a/app/vendor/cakephp/cakephp-codesniffer/CakePHP/Sniffs/Formatting/BlankLineBeforeReturnSniff.php b/app/vendor/cakephp/cakephp-codesniffer/CakePHP/Sniffs/Formatting/BlankLineBeforeReturnSniff.php
index 39fd15204..f5da30288 100644
--- a/app/vendor/cakephp/cakephp-codesniffer/CakePHP/Sniffs/Formatting/BlankLineBeforeReturnSniff.php
+++ b/app/vendor/cakephp/cakephp-codesniffer/CakePHP/Sniffs/Formatting/BlankLineBeforeReturnSniff.php
@@ -56,17 +56,18 @@ public function process(File $phpcsFile, $stackPtr)
$prevLineTokens = [];
while ($current >= 0 && $tokens[$current]['line'] >= $previousLine) {
+ $currentTokenCode = $tokens[$current]['code'];
if (
$tokens[$current]['line'] == $previousLine
- && $tokens[$current]['code'] !== T_WHITESPACE
- && $tokens[$current]['code'] !== T_COMMENT
- && $tokens[$current]['code'] !== T_DOC_COMMENT_OPEN_TAG
- && $tokens[$current]['code'] !== T_DOC_COMMENT_TAG
- && $tokens[$current]['code'] !== T_DOC_COMMENT_STRING
- && $tokens[$current]['code'] !== T_DOC_COMMENT_CLOSE_TAG
- && $tokens[$current]['code'] !== T_DOC_COMMENT_WHITESPACE
+ && $currentTokenCode !== T_WHITESPACE
+ && $currentTokenCode !== T_COMMENT
+ && $currentTokenCode !== T_DOC_COMMENT_OPEN_TAG
+ && $currentTokenCode !== T_DOC_COMMENT_TAG
+ && $currentTokenCode !== T_DOC_COMMENT_STRING
+ && $currentTokenCode !== T_DOC_COMMENT_CLOSE_TAG
+ && $currentTokenCode !== T_DOC_COMMENT_WHITESPACE
) {
- $prevLineTokens[] = $tokens[$current]['code'];
+ $prevLineTokens[] = $currentTokenCode;
}
$current--;
}
diff --git a/app/vendor/cakephp/cakephp-codesniffer/CakePHP/ruleset.xml b/app/vendor/cakephp/cakephp-codesniffer/CakePHP/ruleset.xml
index c5dba1351..5ad91117b 100644
--- a/app/vendor/cakephp/cakephp-codesniffer/CakePHP/ruleset.xml
+++ b/app/vendor/cakephp/cakephp-codesniffer/CakePHP/ruleset.xml
@@ -51,10 +51,15 @@
*/tests/*
-
+
+
+
+
+
+
@@ -81,7 +86,6 @@
-
diff --git a/app/vendor/cakephp/cakephp/VERSION.txt b/app/vendor/cakephp/cakephp/VERSION.txt
index 4ee60801c..7b31d540c 100644
--- a/app/vendor/cakephp/cakephp/VERSION.txt
+++ b/app/vendor/cakephp/cakephp/VERSION.txt
@@ -16,4 +16,4 @@
// @license https://opensource.org/licenses/mit-license.php MIT License
// +--------------------------------------------------------------------------------------------+ //
////////////////////////////////////////////////////////////////////////////////////////////////////
-4.6.0
+4.6.2
diff --git a/app/vendor/cakephp/cakephp/composer.json b/app/vendor/cakephp/cakephp/composer.json
index 0060696c6..7f9c27d9a 100644
--- a/app/vendor/cakephp/cakephp/composer.json
+++ b/app/vendor/cakephp/cakephp/composer.json
@@ -26,7 +26,7 @@
"ext-intl": "*",
"ext-json": "*",
"ext-mbstring": "*",
- "cakephp/chronos": "^2.4.0-RC2",
+ "cakephp/chronos": "^2.4.0",
"composer/ca-bundle": "^1.2",
"laminas/laminas-diactoros": "^2.2.2",
"laminas/laminas-httphandlerrunner": "^1.1 || ^2.0",
diff --git a/app/vendor/cakephp/cakephp/src/Cache/Engine/MemcachedEngine.php b/app/vendor/cakephp/cakephp/src/Cache/Engine/MemcachedEngine.php
index 29c56954a..687987603 100644
--- a/app/vendor/cakephp/cakephp/src/Cache/Engine/MemcachedEngine.php
+++ b/app/vendor/cakephp/cakephp/src/Cache/Engine/MemcachedEngine.php
@@ -365,7 +365,7 @@ public function getMultiple($keys, $default = null): array
$values = $this->_Memcached->getMulti($cacheKeys);
$return = [];
foreach ($cacheKeys as $original => $prefixed) {
- $return[$original] = $values[$prefixed] ?? $default;
+ $return[$original] = array_key_exists($prefixed, $values) ? $values[$prefixed] : $default;
}
return $return;
diff --git a/app/vendor/cakephp/cakephp/src/Cache/Engine/NullEngine.php b/app/vendor/cakephp/cakephp/src/Cache/Engine/NullEngine.php
index 4612a276b..89defe467 100644
--- a/app/vendor/cakephp/cakephp/src/Cache/Engine/NullEngine.php
+++ b/app/vendor/cakephp/cakephp/src/Cache/Engine/NullEngine.php
@@ -62,7 +62,13 @@ public function get($key, $default = null)
*/
public function getMultiple($keys, $default = null): iterable
{
- return [];
+ $result = [];
+
+ foreach ($keys as $key) {
+ $result[$key] = $default;
+ }
+
+ return $result;
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php b/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php
index ac847810f..25fb69f80 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php
@@ -109,7 +109,7 @@ protected function reconnect(): bool
}
try {
- $this->connection->connect();
+ $this->connection->getDriver()->connect();
if ($this->connection->isQueryLoggingEnabled()) {
$this->connection->log('[RECONNECT]');
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php b/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php
index 9f006a1bd..fc06b3118 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php
@@ -203,6 +203,24 @@ protected function _getMethods(Behavior $instance, string $class, string $alias)
return compact('methods', 'finders');
}
+ /**
+ * Set an object directly into the registry by name.
+ *
+ * @param string $name The name of the object to set in the registry.
+ * @param \Cake\ORM\Behavior $object instance to store in the registry
+ * @return $this
+ */
+ public function set(string $name, object $object)
+ {
+ parent::set($name, $object);
+
+ $methods = $this->_getMethods($object, get_class($object), $name);
+ $this->_methodMap += $methods['methods'];
+ $this->_finderMap += $methods['finders'];
+
+ return $this;
+ }
+
/**
* Remove an object from the registry.
*
diff --git a/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php b/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php
index d4fa10a25..21e337dcd 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php
@@ -64,6 +64,7 @@ class EagerLoader
'joinType' => 1,
'strategy' => 1,
'negateMatch' => 1,
+ 'includeFields' => 1,
];
/**
diff --git a/app/vendor/cakephp/twig-view/README.md b/app/vendor/cakephp/twig-view/README.md
index fca06df62..ca1eab94b 100644
--- a/app/vendor/cakephp/twig-view/README.md
+++ b/app/vendor/cakephp/twig-view/README.md
@@ -7,13 +7,13 @@
[](LICENSE)
-This plugin allows you to use the [Twig Templating Language](http://twig.sensiolabs.org/documentation) for your views.
+This plugin allows you to use the [Twig Templating Language](https://twig.symfony.com/doc) for your views.
It provides wrappers for common View opertions and many helpful extensions that expose CakePHP functions and `jasny/twig-extensions` helpers.
## Installation
-To install with [Composer](http://getcomposer.org/), use the command below.
+To install with [Composer](https://getcomposer.org/), use the command below.
```bash
composer require cakephp/twig-view
@@ -205,8 +205,8 @@ All wrapper functions are pre-escaped and do not require using `|raw` filter. Ho
### Extension Filters
-* `low` maps to [`strtolower`](http://php.net/strtolower)
-* `up` maps to [`strtoupper`](http://php.net/strtoupper)
+* `low` maps to [`strtolower`](https://php.net/strtolower)
+* `up` maps to [`strtoupper`](https://php.net/strtoupper)
* `env` maps to [`env`](https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#global-functions)
* `pluralize` maps to [`Cake\Utility\Inflector::pluralize`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::pluralize)
* `singularize` maps to [`Cake\Utility\Inflector::singularize`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::singularize)
@@ -222,7 +222,7 @@ All wrapper functions are pre-escaped and do not require using `|raw` filter. Ho
* `cake_number_format` maps to [`Cake\I18n\Number::format`](https://book.cakephp.org/4/en/core-libraries/number.html#Cake\\I18n\\Number::format)
* `formatDelta` maps to [`Cake\I18n\Number::formatDelta`](https://book.cakephp.org/4/en/core-libraries/number.html#Cake\\I18n\\Number::formatDelta)
* `currency` maps to [`Cake\I18n\Number::currency`](https://book.cakephp.org/4/en/core-libraries/number.html#Cake\\I18n\\Number::currency)
-* `substr` maps to [`substr`](http://php.net/substr)
+* `substr` maps to [`substr`](https://php.net/substr)
* `tokenize` maps to [`Cake\Utility\Text::tokenize`](https://book.cakephp.org/4/en/core-libraries/text.html#simple-string-parsing)
* `insert` maps to [`Cake\Utility\Text::insert`](https://book.cakephp.org/4/en/core-libraries/text.html#formatting-strings)
* `cleanInsert` maps to [`Cake\Utility\Text::cleanInsert`](https://book.cakephp.org/4/en/core-libraries/text.html#formatting-strings)
@@ -239,24 +239,24 @@ All wrapper functions are pre-escaped and do not require using `|raw` filter. Ho
* `utf8` maps to `Cake\Utility\Text::utf8`
* `ascii` maps to `Cake\Utility\Text::ascii`
* `parseFileSize` maps to [`Cake\Utility\Text::parseFileSize`](https://book.cakephp.org/4/en/core-libraries/text.html#simple-string-parsing)
-* `serialize` maps to [`serialize`](http://php.net/serialize)
-* `unserialize` maps to [`unserialize`](http://php.net/unserialize)
-* `md5` maps to [`md5`](http://php.net/md5)
-* `base64_encode` maps to [`base64_encode`](http://php.net/base64_encode)
-* `base64_decode` maps to [`base64_decode`](http://php.net/base64_decode)
-* `string` cast to [`string`](http://php.net/manual/en/language.types.type-juggling.php)
+* `serialize` maps to [`serialize`](https://php.net/serialize)
+* `unserialize` maps to [`unserialize`](https://php.net/unserialize)
+* `md5` maps to [`md5`](https://php.net/md5)
+* `base64_encode` maps to [`base64_encode`](https://php.net/base64_encode)
+* `base64_decode` maps to [`base64_decode`](https://php.net/base64_decode)
+* `string` cast to [`string`](https://php.net/manual/en/language.types.type-juggling.php)
See `jasny/twig-extensions` for the filters they provide.
### Extension Functions
-* `in_array` maps to [`in_array`](http://php.net/in_array)
-* `explode` maps to [`explode`](http://php.net/explode)
-* `array` cast to [`array`](http://php.net/manual/en/language.types.type-juggling.php)
-* `array_push` maps to [`push`](http://php.net/array_push)
-* `array_prev` maps to [`prev`](http://php.net/prev)
-* `array_next` maps to [`next`](http://php.net/next)
-* `array_current` maps to [`current`](http://php.net/current)
+* `in_array` maps to [`in_array`](https://php.net/in_array)
+* `explode` maps to [`explode`](https://php.net/explode)
+* `array` cast to [`array`](https://php.net/manual/en/language.types.type-juggling.php)
+* `array_push` maps to [`push`](https://php.net/array_push)
+* `array_prev` maps to [`prev`](https://php.net/prev)
+* `array_next` maps to [`next`](https://php.net/next)
+* `array_current` maps to [`current`](https://php.net/current)
* `__` maps to [`__`](https://book.cakephp.org/4/en/core-libraries/internationalization-and-localization.html)
* `__d` maps to [`__d`](https://book.cakephp.org/4/en/core-libraries/internationalization-and-localization.html)
* `__n` maps to [`__n`](https://book.cakephp.org/4/en/core-libraries/internationalization-and-localization.html)
diff --git a/app/vendor/cakephp/twig-view/composer.json b/app/vendor/cakephp/twig-view/composer.json
index fff940a58..3c3640a8b 100644
--- a/app/vendor/cakephp/twig-view/composer.json
+++ b/app/vendor/cakephp/twig-view/composer.json
@@ -22,11 +22,10 @@
"source": "https://github.com/cakephp/twig-view"
},
"require": {
- "php": ">=7.2",
"cakephp/cakephp": "^4.0",
"jasny/twig-extensions": "^1.3",
"twig/markdown-extra": "^3.0",
- "twig/twig": "^3.0"
+ "twig/twig": "^3.11.0"
},
"require-dev": {
"cakephp/cakephp-codesniffer": "^4.0",
@@ -64,12 +63,16 @@
"@phpstan",
"@psalm"
],
- "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12.54 psalm/phar:~4.3.0 && mv composer.backup composer.json",
+ "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:~1.7.0 psalm/phar:~4.23.0 && mv composer.backup composer.json",
"test": [
"phpunit"
]
},
"config": {
- "sort-packages": true
+ "sort-packages": true,
+ "allow-plugins": {
+ "dealerdirect/phpcodesniffer-composer-installer": true,
+ "cakephp/plugin-installer": true
+ }
}
}
diff --git a/app/vendor/cakephp/twig-view/src/Twig/Extension/I18nExtension.php b/app/vendor/cakephp/twig-view/src/Twig/Extension/I18nExtension.php
index 3b52084c9..c5977e3e5 100644
--- a/app/vendor/cakephp/twig-view/src/Twig/Extension/I18nExtension.php
+++ b/app/vendor/cakephp/twig-view/src/Twig/Extension/I18nExtension.php
@@ -35,10 +35,13 @@ public function getFunctions(): array
{
return [
new TwigFunction('__', '__'),
- new TwigFunction('__d', '__d'),
new TwigFunction('__n', '__n'),
- new TwigFunction('__x', '__x'),
+ new TwigFunction('__d', '__d'),
new TwigFunction('__dn', '__dn'),
+ new TwigFunction('__x', '__x'),
+ new TwigFunction('__xn', '__xn'),
+ new TwigFunction('__dx', '__dx'),
+ new TwigFunction('__dxn', '__dxn'),
];
}
}
diff --git a/app/vendor/cakephp/twig-view/src/View/TwigView.php b/app/vendor/cakephp/twig-view/src/View/TwigView.php
index 2be780314..2c35a47df 100644
--- a/app/vendor/cakephp/twig-view/src/View/TwigView.php
+++ b/app/vendor/cakephp/twig-view/src/View/TwigView.php
@@ -64,12 +64,12 @@ class TwigView extends View
* Use ViewBuilder::setOption()/setOptions() in your controller to set these options.
*
* - `environment` - Array of config you would pass into \Twig\Environment to overwrite the default settings.
- * See http://twig.sensiolabs.org/doc/api.html#environment-options.
+ * See https://twig.symfony.com/doc/3.x/api.html#environment-options.
* - `markdown` - Set to 'default' to use `DefaultMarkdown` or
* provide custom Twig\Extra\Markdown\MarkdownInterface instance.
* See https://twig.symfony.com/doc/3.x/filters/markdown_to_html.html.
*
- * @var array
+ * @var array
*/
protected $_defaultConfig = [
'environment' => [
diff --git a/app/vendor/composer/ClassLoader.php b/app/vendor/composer/ClassLoader.php
index afef3fa2a..a72151c77 100644
--- a/app/vendor/composer/ClassLoader.php
+++ b/app/vendor/composer/ClassLoader.php
@@ -42,6 +42,9 @@
*/
class ClassLoader
{
+ /** @var \Closure(string):void */
+ private static $includeFile;
+
/** @var ?string */
private $vendorDir;
@@ -106,6 +109,7 @@ class ClassLoader
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
+ self::initializeIncludeClosure();
}
/**
@@ -425,7 +429,8 @@ public function unregister()
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
- includeFile($file);
+ $includeFile = self::$includeFile;
+ $includeFile($file);
return true;
}
@@ -555,18 +560,26 @@ private function findFileWithExtension($class, $ext)
return false;
}
-}
-/**
- * Scope isolated include.
- *
- * Prevents access to $this/self from included files.
- *
- * @param string $file
- * @return void
- * @private
- */
-function includeFile($file)
-{
- include $file;
+ /**
+ * @return void
+ */
+ private static function initializeIncludeClosure()
+ {
+ if (self::$includeFile !== null) {
+ return;
+ }
+
+ /**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param string $file
+ * @return void
+ */
+ self::$includeFile = \Closure::bind(static function($file) {
+ include $file;
+ }, null, null);
+ }
}
diff --git a/app/vendor/composer/autoload_files.php b/app/vendor/composer/autoload_files.php
index a3f9ae503..2929593d3 100644
--- a/app/vendor/composer/autoload_files.php
+++ b/app/vendor/composer/autoload_files.php
@@ -6,9 +6,9 @@
$baseDir = dirname($vendorDir);
return array(
+ '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
- '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'89efb1254ef2d1c5d80096acd12c4098' => $vendorDir . '/twig/twig/src/Resources/core.php',
'ffecb95d45175fd40f75be8a23b34f90' => $vendorDir . '/twig/twig/src/Resources/debug.php',
'c7baa00073ee9c61edf148c51917cfb4' => $vendorDir . '/twig/twig/src/Resources/escaper.php',
@@ -43,6 +43,7 @@
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
+ 'f278094c42a52b6bff77f375d59c1278' => $vendorDir . '/twig/markdown-extra/Resources/functions.php',
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
diff --git a/app/vendor/composer/autoload_psr4.php b/app/vendor/composer/autoload_psr4.php
index 2dbb2f4f2..21a723094 100644
--- a/app/vendor/composer/autoload_psr4.php
+++ b/app/vendor/composer/autoload_psr4.php
@@ -8,6 +8,8 @@
return array(
'Twig\\Extra\\Markdown\\' => array($vendorDir . '/twig/markdown-extra'),
'Twig\\' => array($vendorDir . '/twig/twig/src'),
+ 'TestPlugin\\Test\\' => array($baseDir . '/availableplugins/TestPlugin/tests'),
+ 'TestPlugin\\' => array($baseDir . '/availableplugins/TestPlugin/src'),
'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'),
@@ -24,6 +26,8 @@
'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
'Symfony\\Component\\Config\\' => array($vendorDir . '/symfony/config'),
+ 'SshKeyAuthenticator\\Test\\' => array($baseDir . '/plugins/SshKeyAuthenticator/tests'),
+ 'SshKeyAuthenticator\\' => array($baseDir . '/plugins/SshKeyAuthenticator/src'),
'SqlConnector\\Test\\' => array($baseDir . '/availableplugins/SqlConnector/tests'),
'SqlConnector\\' => array($baseDir . '/availableplugins/SqlConnector/src'),
'SlevomatCodingStandard\\' => array($vendorDir . '/slevomat/coding-standard/SlevomatCodingStandard'),
@@ -43,12 +47,15 @@
'PipelineToolkit\\' => array($baseDir . '/availableplugins/PipelineToolkit/src'),
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
'Phinx\\' => array($vendorDir . '/robmorgan/phinx/src/Phinx'),
+ 'PasswordAuthenticator\\Test\\' => array($baseDir . '/availableplugins/PasswordAuthenticator/tests'),
+ 'PasswordAuthenticator\\' => array($baseDir . '/availableplugins/PasswordAuthenticator/src'),
'PHPStan\\PhpDocParser\\' => array($vendorDir . '/phpstan/phpdoc-parser/src'),
'PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => array($vendorDir . '/dealerdirect/phpcodesniffer-composer-installer/src'),
'OrcidSource\\Test\\' => array($baseDir . '/plugins/OrcidSource/tests'),
'OrcidSource\\' => array($baseDir . '/plugins/OrcidSource/src'),
'Migrations\\' => array($vendorDir . '/cakephp/migrations/src'),
'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'),
+ 'MabeEnum\\' => array($vendorDir . '/marc-mabe/php-enum/src'),
'M1\\Env\\' => array($vendorDir . '/m1/env/src'),
'League\\Uri\\' => array($vendorDir . '/league/uri', $vendorDir . '/league/uri-interfaces'),
'League\\Container\\' => array($vendorDir . '/league/container/src'),
@@ -62,15 +69,16 @@
'EnvSource\\' => array($baseDir . '/plugins/EnvSource/src'),
'Doctrine\\SqlFormatter\\' => array($vendorDir . '/doctrine/sql-formatter/src'),
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
- 'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/lib/Doctrine/Deprecations'),
+ 'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'),
'Doctrine\\DBAL\\' => array($vendorDir . '/doctrine/dbal/src'),
- 'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache'),
'Doctrine\\Common\\' => array($vendorDir . '/doctrine/event-manager/src'),
'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
'DebugKit\\Test\\Fixture\\' => array($vendorDir . '/cakephp/debug_kit/tests/Fixture'),
'DebugKit\\' => array($vendorDir . '/cakephp/debug_kit/src'),
'CoreServer\\Test\\' => array($baseDir . '/plugins/CoreServer/tests'),
'CoreServer\\' => array($baseDir . '/plugins/CoreServer/src'),
+ 'CoreReport\\Test\\' => array($baseDir . '/plugins/CoreReport/tests'),
+ 'CoreReport\\' => array($baseDir . '/plugins/CoreReport/src'),
'CoreJob\\Test\\' => array($baseDir . '/plugins/CoreJob/tests'),
'CoreJob\\' => array($baseDir . '/plugins/CoreJob/src'),
'CoreEnroller\\Test\\' => array($baseDir . '/plugins/CoreEnroller/tests'),
diff --git a/app/vendor/composer/autoload_real.php b/app/vendor/composer/autoload_real.php
index ea4df5fa0..8072a483a 100644
--- a/app/vendor/composer/autoload_real.php
+++ b/app/vendor/composer/autoload_real.php
@@ -33,25 +33,18 @@ public static function getLoader()
$loader->register(true);
- $includeFiles = \Composer\Autoload\ComposerStaticInitb25f76eec921984aa94dcf4015a4846e::$files;
- foreach ($includeFiles as $fileIdentifier => $file) {
- composerRequireb25f76eec921984aa94dcf4015a4846e($fileIdentifier, $file);
+ $filesToLoad = \Composer\Autoload\ComposerStaticInitb25f76eec921984aa94dcf4015a4846e::$files;
+ $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+
+ require $file;
+ }
+ }, null, null);
+ foreach ($filesToLoad as $fileIdentifier => $file) {
+ $requireFile($fileIdentifier, $file);
}
return $loader;
}
}
-
-/**
- * @param string $fileIdentifier
- * @param string $file
- * @return void
- */
-function composerRequireb25f76eec921984aa94dcf4015a4846e($fileIdentifier, $file)
-{
- if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
- $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
-
- require $file;
- }
-}
diff --git a/app/vendor/composer/autoload_static.php b/app/vendor/composer/autoload_static.php
index d5738fcc7..93eb7e9c7 100644
--- a/app/vendor/composer/autoload_static.php
+++ b/app/vendor/composer/autoload_static.php
@@ -7,9 +7,9 @@
class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
{
public static $files = array (
+ '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
- '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'89efb1254ef2d1c5d80096acd12c4098' => __DIR__ . '/..' . '/twig/twig/src/Resources/core.php',
'ffecb95d45175fd40f75be8a23b34f90' => __DIR__ . '/..' . '/twig/twig/src/Resources/debug.php',
'c7baa00073ee9c61edf148c51917cfb4' => __DIR__ . '/..' . '/twig/twig/src/Resources/escaper.php',
@@ -44,6 +44,7 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
+ 'f278094c42a52b6bff77f375d59c1278' => __DIR__ . '/..' . '/twig/markdown-extra/Resources/functions.php',
'6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'ec07570ca5a812141189b1fa81503674' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
@@ -55,6 +56,8 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
array (
'Twig\\Extra\\Markdown\\' => 20,
'Twig\\' => 5,
+ 'TestPlugin\\Test\\' => 16,
+ 'TestPlugin\\' => 11,
),
'S' =>
array (
@@ -74,6 +77,8 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
'Symfony\\Component\\Filesystem\\' => 29,
'Symfony\\Component\\Console\\' => 26,
'Symfony\\Component\\Config\\' => 25,
+ 'SshKeyAuthenticator\\Test\\' => 25,
+ 'SshKeyAuthenticator\\' => 20,
'SqlConnector\\Test\\' => 18,
'SqlConnector\\' => 13,
'SlevomatCodingStandard\\' => 23,
@@ -99,18 +104,21 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
'PipelineToolkit\\' => 16,
'PhpParser\\' => 10,
'Phinx\\' => 6,
+ 'PasswordAuthenticator\\Test\\' => 27,
+ 'PasswordAuthenticator\\' => 22,
'PHPStan\\PhpDocParser\\' => 21,
'PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => 57,
),
- 'O' =>
+ 'O' =>
array (
'OrcidSource\\Test\\' => 17,
'OrcidSource\\' => 12,
),
- 'M' =>
+ 'M' =>
array (
'Migrations\\' => 11,
'Masterminds\\' => 12,
+ 'MabeEnum\\' => 9,
'M1\\Env\\' => 7,
),
'L' =>
@@ -141,7 +149,6 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
'Doctrine\\Instantiator\\' => 22,
'Doctrine\\Deprecations\\' => 22,
'Doctrine\\DBAL\\' => 14,
- 'Doctrine\\Common\\Cache\\' => 22,
'Doctrine\\Common\\' => 16,
'DeepCopy\\' => 9,
'DebugKit\\Test\\Fixture\\' => 22,
@@ -151,6 +158,8 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
array (
'CoreServer\\Test\\' => 16,
'CoreServer\\' => 11,
+ 'CoreReport\\Test\\' => 16,
+ 'CoreReport\\' => 11,
'CoreJob\\Test\\' => 13,
'CoreJob\\' => 8,
'CoreEnroller\\Test\\' => 18,
@@ -197,6 +206,14 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
array (
0 => __DIR__ . '/..' . '/twig/twig/src',
),
+ 'TestPlugin\\Test\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/availableplugins/TestPlugin/tests',
+ ),
+ 'TestPlugin\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/availableplugins/TestPlugin/src',
+ ),
'Symfony\\Polyfill\\Php81\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php81',
@@ -261,6 +278,14 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
array (
0 => __DIR__ . '/..' . '/symfony/config',
),
+ 'SshKeyAuthenticator\\Test\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/plugins/SshKeyAuthenticator/tests',
+ ),
+ 'SshKeyAuthenticator\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/plugins/SshKeyAuthenticator/src',
+ ),
'SqlConnector\\Test\\' =>
array (
0 => __DIR__ . '/../..' . '/availableplugins/SqlConnector/tests',
@@ -339,6 +364,14 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
array (
0 => __DIR__ . '/..' . '/robmorgan/phinx/src/Phinx',
),
+ 'PasswordAuthenticator\\Test\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/availableplugins/PasswordAuthenticator/tests',
+ ),
+ 'PasswordAuthenticator\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/availableplugins/PasswordAuthenticator/src',
+ ),
'PHPStan\\PhpDocParser\\' =>
array (
0 => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src',
@@ -347,15 +380,15 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
array (
0 => __DIR__ . '/..' . '/dealerdirect/phpcodesniffer-composer-installer/src',
),
- 'OrcidSource\\Test\\' =>
+ 'OrcidSource\\Test\\' =>
array (
0 => __DIR__ . '/../..' . '/plugins/OrcidSource/tests',
),
- 'OrcidSource\\' =>
+ 'OrcidSource\\' =>
array (
0 => __DIR__ . '/../..' . '/plugins/OrcidSource/src',
),
- 'Migrations\\' =>
+ 'Migrations\\' =>
array (
0 => __DIR__ . '/..' . '/cakephp/migrations/src',
),
@@ -363,6 +396,10 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
array (
0 => __DIR__ . '/..' . '/masterminds/html5/src',
),
+ 'MabeEnum\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/marc-mabe/php-enum/src',
+ ),
'M1\\Env\\' =>
array (
0 => __DIR__ . '/..' . '/m1/env/src',
@@ -418,16 +455,12 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
),
'Doctrine\\Deprecations\\' =>
array (
- 0 => __DIR__ . '/..' . '/doctrine/deprecations/lib/Doctrine/Deprecations',
+ 0 => __DIR__ . '/..' . '/doctrine/deprecations/src',
),
'Doctrine\\DBAL\\' =>
array (
0 => __DIR__ . '/..' . '/doctrine/dbal/src',
),
- 'Doctrine\\Common\\Cache\\' =>
- array (
- 0 => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache',
- ),
'Doctrine\\Common\\' =>
array (
0 => __DIR__ . '/..' . '/doctrine/event-manager/src',
@@ -452,6 +485,14 @@ class ComposerStaticInitb25f76eec921984aa94dcf4015a4846e
array (
0 => __DIR__ . '/../..' . '/plugins/CoreServer/src',
),
+ 'CoreReport\\Test\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/plugins/CoreReport/tests',
+ ),
+ 'CoreReport\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/plugins/CoreReport/src',
+ ),
'CoreJob\\Test\\' =>
array (
0 => __DIR__ . '/../..' . '/plugins/CoreJob/tests',
diff --git a/app/vendor/composer/ca-bundle/res/cacert.pem b/app/vendor/composer/ca-bundle/res/cacert.pem
index 584af3c0b..4acd8e536 100644
--- a/app/vendor/composer/ca-bundle/res/cacert.pem
+++ b/app/vendor/composer/ca-bundle/res/cacert.pem
@@ -1,14 +1,14 @@
##
## Bundle of CA Root Certificates
##
-## Certificate data from Mozilla as of: Tue Feb 25 04:12:03 2025 GMT
+## Certificate data from Mozilla as of: Tue May 20 03:12:02 2025 GMT
##
## Find updated versions here: https://curl.se/docs/caextract.html
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
## file (certdata.txt). This file can be found in the mozilla source tree:
-## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
+## https://raw.githubusercontent.com/mozilla-firefox/firefox/refs/heads/release/security/nss/lib/ckfw/builtins/certdata.txt
##
## It contains the certificates in PEM format and therefore
## can be directly used with curl / libcurl / php_curl, or with
@@ -16,76 +16,10 @@
## Just configure this file as the SSLCACertificateFile.
##
## Conversion done with mk-ca-bundle.pl version 1.29.
-## SHA256: 620fd89c02acb0019f1899dab7907db5d20735904f5a9a0d3a8771a5857ac482
+## SHA256: 8944ec6b572b577daee4fc681a425881f841ec2660e4cb5f0eee727f84620697
##
-GlobalSign Root CA
-==================
------BEGIN CERTIFICATE-----
-MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
-GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
-b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
-BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
-VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
-DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
-THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
-Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
-c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
-gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
-HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
-AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
-Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
-j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
-hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
-X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
------END CERTIFICATE-----
-
-Entrust.net Premium 2048 Secure Server CA
-=========================================
------BEGIN CERTIFICATE-----
-MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
-ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
-bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
-BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
-NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
-d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
-MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
-ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
-Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
-hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
-nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
-VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
-BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
-KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
-T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
-zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
-J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
-nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
------END CERTIFICATE-----
-
-Baltimore CyberTrust Root
-=========================
------BEGIN CERTIFICATE-----
-MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
-ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
-ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
-SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
-dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
-uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
-UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
-G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
-XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
-l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
-VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
-BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
-cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
-hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
-Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
-RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
------END CERTIFICATE-----
-
Entrust Root Certification Authority
====================================
-----BEGIN CERTIFICATE-----
@@ -112,30 +46,6 @@ W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
-----END CERTIFICATE-----
-Comodo AAA Services root
-========================
------BEGIN CERTIFICATE-----
-MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
-R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
-TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
-MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
-c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
-BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
-C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
-i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
-Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
-Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
-Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
-BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
-cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
-LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
-7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
-Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
-8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
-12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
------END CERTIFICATE-----
-
QuoVadis Root CA 2
==================
-----BEGIN CERTIFICATE-----
@@ -202,78 +112,6 @@ vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
-----END CERTIFICATE-----
-XRamp Global CA Root
-====================
------BEGIN CERTIFICATE-----
-MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
-BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
-dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
-dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
-HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
-U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
-IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
-foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
-zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
-AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
-xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
-EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
-oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
-AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
-/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
-qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
-nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
-8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
------END CERTIFICATE-----
-
-Go Daddy Class 2 CA
-===================
------BEGIN CERTIFICATE-----
-MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
-VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
-ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
-A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
-RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
-ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
-2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
-qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
-YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
-vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
-BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
-atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
-MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
-PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
-I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
-HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
-Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
-vZ8=
------END CERTIFICATE-----
-
-Starfield Class 2 CA
-====================
------BEGIN CERTIFICATE-----
-MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
-U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
-Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
-MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
-A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
-SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
-bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
-JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
-epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
-F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
-MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
-hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
-bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
-QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
-afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
-PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
-xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
-KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
-QBFGmh95DmK/D5fs4C8fF5Q=
------END CERTIFICATE-----
-
DigiCert Assured ID Root CA
===========================
-----BEGIN CERTIFICATE-----
diff --git a/app/vendor/composer/class-map-generator/README.md b/app/vendor/composer/class-map-generator/README.md
index 4b5d6a26d..ff27e2ea3 100644
--- a/app/vendor/composer/class-map-generator/README.md
+++ b/app/vendor/composer/class-map-generator/README.md
@@ -12,7 +12,7 @@ Installation
Install the latest version with:
```bash
-$ composer require composer/class-map-generator
+composer require composer/class-map-generator
```
diff --git a/app/vendor/composer/class-map-generator/composer.json b/app/vendor/composer/class-map-generator/composer.json
index 59aa759e7..496912c26 100644
--- a/app/vendor/composer/class-map-generator/composer.json
+++ b/app/vendor/composer/class-map-generator/composer.json
@@ -19,11 +19,11 @@
"composer/pcre": "^2.1 || ^3.1"
},
"require-dev": {
- "symfony/phpunit-bridge": "^5",
- "phpstan/phpstan": "^1.6",
- "phpstan/phpstan-deprecation-rules": "^1",
- "phpstan/phpstan-strict-rules": "^1.1",
- "phpstan/phpstan-phpunit": "^1",
+ "phpunit/phpunit": "^8",
+ "phpstan/phpstan": "^1.12 || ^2",
+ "phpstan/phpstan-deprecation-rules": "^1 || ^2",
+ "phpstan/phpstan-strict-rules": "^1.1 || ^2",
+ "phpstan/phpstan-phpunit": "^1 || ^2",
"symfony/filesystem": "^5.4 || ^6"
},
"autoload": {
@@ -42,7 +42,7 @@
}
},
"scripts": {
- "test": "SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor/bin/simple-phpunit",
- "phpstan": "phpstan analyse"
+ "test": "@php phpunit",
+ "phpstan": "@php phpstan analyse"
}
}
diff --git a/app/vendor/composer/class-map-generator/src/ClassMap.php b/app/vendor/composer/class-map-generator/src/ClassMap.php
index d6e2899c2..797efc688 100644
--- a/app/vendor/composer/class-map-generator/src/ClassMap.php
+++ b/app/vendor/composer/class-map-generator/src/ClassMap.php
@@ -12,6 +12,8 @@
namespace Composer\ClassMapGenerator;
+use Composer\Pcre\Preg;
+
/**
* @author Jordi Boggiano
*/
@@ -28,7 +30,7 @@ class ClassMap implements \Countable
private $ambiguousClasses = [];
/**
- * @var string[]
+ * @var array>
*/
private $psrViolations = [];
@@ -55,7 +57,13 @@ public function getMap(): array
*/
public function getPsrViolations(): array
{
- return $this->psrViolations;
+ if (\count($this->psrViolations) === 0) {
+ return [];
+ }
+
+ return array_map(static function (array $violation): string {
+ return $violation['warning'];
+ }, array_merge(...array_values($this->psrViolations)));
}
/**
@@ -65,11 +73,36 @@ public function getPsrViolations(): array
*
* To get the path the class is being mapped to, call getClassPath
*
+ * By default, paths that contain test(s), fixture(s), example(s) or stub(s) are ignored
+ * as those are typically not problematic when they're dummy classes in the tests folder.
+ * If you want to get these back as well you can pass false to $duplicatesFilter. Or
+ * you can pass your own pattern to exclude if you need to change the default.
+ *
+ * @param non-empty-string|false $duplicatesFilter
+ *
* @return array>
*/
- public function getAmbiguousClasses(): array
+ public function getAmbiguousClasses($duplicatesFilter = '{/(test|fixture|example|stub)s?/}i'): array
{
- return $this->ambiguousClasses;
+ if (false === $duplicatesFilter) {
+ return $this->ambiguousClasses;
+ }
+
+ if (true === $duplicatesFilter) {
+ throw new \InvalidArgumentException('$duplicatesFilter should be false or a string with a valid regex, got true.');
+ }
+
+ $ambiguousClasses = [];
+ foreach ($this->ambiguousClasses as $class => $paths) {
+ $paths = array_filter($paths, function ($path) use ($duplicatesFilter) {
+ return !Preg::isMatch($duplicatesFilter, strtr($path, '\\', '/'));
+ });
+ if (\count($paths) > 0) {
+ $ambiguousClasses[$class] = array_values($paths);
+ }
+ }
+
+ return $ambiguousClasses;
}
/**
@@ -86,6 +119,8 @@ public function sort(): void
*/
public function addClass(string $className, string $path): void
{
+ unset($this->psrViolations[strtr($path, '\\', '/')]);
+
$this->map[$className] = $path;
}
@@ -110,9 +145,22 @@ public function hasClass(string $className): bool
return isset($this->map[$className]);
}
- public function addPsrViolation(string $warning): void
+ public function addPsrViolation(string $warning, string $className, string $path): void
{
- $this->psrViolations[] = $warning;
+ $path = rtrim(strtr($path, '\\', '/'), '/');
+
+ $this->psrViolations[$path][] = ['warning' => $warning, 'className' => $className];
+ }
+
+ public function clearPsrViolationsByPath(string $pathPrefix): void
+ {
+ $pathPrefix = rtrim(strtr($pathPrefix, '\\', '/'), '/');
+
+ foreach ($this->psrViolations as $path => $violations) {
+ if ($path === $pathPrefix || 0 === \strpos($path, $pathPrefix.'/')) {
+ unset($this->psrViolations[$path]);
+ }
+ }
}
/**
@@ -128,4 +176,16 @@ public function count(): int
{
return \count($this->map);
}
+
+ /**
+ * Get the raw psr violations
+ *
+ * This is a map of filepath to an associative array of the warning string
+ * and the offending class name.
+ * @return array>
+ */
+ public function getRawPsrViolations(): array
+ {
+ return $this->psrViolations;
+ }
}
diff --git a/app/vendor/composer/class-map-generator/src/ClassMapGenerator.php b/app/vendor/composer/class-map-generator/src/ClassMapGenerator.php
index fd905c3ca..2bfa1ed97 100644
--- a/app/vendor/composer/class-map-generator/src/ClassMapGenerator.php
+++ b/app/vendor/composer/class-map-generator/src/ClassMapGenerator.php
@@ -45,6 +45,11 @@ class ClassMapGenerator
*/
private $classMap;
+ /**
+ * @var non-empty-string
+ */
+ private $streamWrappersRegex;
+
/**
* @param list $extensions File extensions to scan for classes in the given paths
*/
@@ -52,6 +57,7 @@ public function __construct(array $extensions = ['php', 'inc'])
{
$this->extensions = $extensions;
$this->classMap = new ClassMap;
+ $this->streamWrappersRegex = sprintf('{^(?:%s)://}', implode('|', array_map('preg_quote', stream_get_wrappers())));
}
/**
@@ -61,7 +67,7 @@ public function __construct(array $extensions = ['php', 'inc'])
*
* @return $this
*/
- public function avoidDuplicateScans(FileList $scannedFiles = null): self
+ public function avoidDuplicateScans(?FileList $scannedFiles = null): self
{
$this->scannedFiles = $scannedFiles ?? new FileList;
@@ -97,10 +103,11 @@ public function getClassMap(): ClassMap
* @param non-empty-string|null $excluded Regex that matches file paths to be excluded from the classmap
* @param 'classmap'|'psr-0'|'psr-4' $autoloadType Optional autoload standard to use mapping rules with the namespace instead of purely doing a classmap
* @param string|null $namespace Optional namespace prefix to filter by, only for psr-0/psr-4 autoloading
+ * @param array $excludedDirs Optional dirs to exclude from search relative to $path
*
* @throws \RuntimeException When the path is neither an existing file nor directory
*/
- public function scanPaths($path, string $excluded = null, string $autoloadType = 'classmap', ?string $namespace = null): void
+ public function scanPaths($path, ?string $excluded = null, string $autoloadType = 'classmap', ?string $namespace = null, array $excludedDirs = []): void
{
if (!in_array($autoloadType, ['psr-0', 'psr-4', 'classmap'], true)) {
throw new \InvalidArgumentException('$autoloadType must be one of: "psr-0", "psr-4" or "classmap"');
@@ -124,7 +131,8 @@ public function scanPaths($path, string $excluded = null, string $autoloadType =
->files()
->followLinks()
->name('/\.(?:'.implode('|', array_map('preg_quote', $this->extensions)).')$/')
- ->in($path);
+ ->in($path)
+ ->exclude($excludedDirs);
} else {
throw new \RuntimeException(
'Could not scan for classes inside "'.$path.'" which does not appear to be a file nor a folder'
@@ -140,18 +148,21 @@ public function scanPaths($path, string $excluded = null, string $autoloadType =
continue;
}
- if (!self::isAbsolutePath($filePath)) {
+ $isStreamWrapperPath = Preg::isMatch($this->streamWrappersRegex, $filePath);
+ if (!self::isAbsolutePath($filePath) && !$isStreamWrapperPath) {
$filePath = $cwd . '/' . $filePath;
$filePath = self::normalizePath($filePath);
} else {
- $filePath = Preg::replace('{[\\\\/]{2,}}', '/', $filePath);
+ $filePath = Preg::replace('{(?getPathname());
}
- $realPath = realpath($filePath);
+ $realPath = $isStreamWrapperPath
+ ? $filePath
+ : realpath($filePath);
// fallback just in case but this really should not happen
if (false === $realPath) {
@@ -189,7 +200,7 @@ public function scanPaths($path, string $excluded = null, string $autoloadType =
foreach ($classes as $class) {
if (!$this->classMap->hasClass($class)) {
$this->classMap->addClass($class, $filePath);
- } elseif ($filePath !== $this->classMap->getClassPath($class) && !Preg::isMatch('{/(test|fixture|example|stub)s?/}i', strtr($this->classMap->getClassPath($class).' '.$filePath, '\\', '/'))) {
+ } elseif ($filePath !== $this->classMap->getClassPath($class)) {
$this->classMap->addAmbiguousClass($class, $filePath);
}
}
@@ -205,6 +216,8 @@ public function scanPaths($path, string $excluded = null, string $autoloadType =
* @param 'psr-0'|'psr-4' $namespaceType
* @param string $basePath root directory of given autoload mapping
* @return array valid classes
+ *
+ * @throws \InvalidArgumentException When namespaceType is neither psr-0 nor psr-4
*/
private function filterByNamespace(array $classes, string $filePath, string $baseNamespace, string $namespaceType, string $basePath): array
{
@@ -216,10 +229,6 @@ private function filterByNamespace(array $classes, string $filePath, string $bas
$realSubPath = substr($realSubPath, 0, $dotPosition === false ? PHP_INT_MAX : $dotPosition);
foreach ($classes as $class) {
- // silently skip if ns doesn't have common root
- if ('' !== $baseNamespace && 0 !== strpos($class, $baseNamespace)) {
- continue;
- }
// transform class name to file path and validate
if ('psr-0' === $namespaceType) {
$namespaceLength = strrpos($class, '\\');
@@ -245,8 +254,16 @@ private function filterByNamespace(array $classes, string $filePath, string $bas
}
// warn only if no valid classes, else silently skip invalid
if (\count($validClasses) === 0) {
+ $cwd = realpath(self::getCwd());
+ if ($cwd === false) {
+ $cwd = self::getCwd();
+ }
+ $cwd = self::normalizePath($cwd);
+ $shortPath = Preg::replace('{^'.preg_quote($cwd).'}', '.', self::normalizePath($filePath), 1);
+ $shortBasePath = Preg::replace('{^'.preg_quote($cwd).'}', '.', self::normalizePath($basePath), 1);
+
foreach ($rejectedClasses as $class) {
- $this->classMap->addPsrViolation("Class $class located in ".Preg::replace('{^'.preg_quote(self::getCwd()).'}', '.', $filePath, 1)." does not comply with $namespaceType autoloading standard. Skipping.");
+ $this->classMap->addPsrViolation("Class $class located in $shortPath does not comply with $namespaceType autoloading standard (rule: $baseNamespace => $shortBasePath). Skipping.", $class, $filePath);
}
return [];
diff --git a/app/vendor/composer/class-map-generator/src/PhpFileCleaner.php b/app/vendor/composer/class-map-generator/src/PhpFileCleaner.php
index 3a74478e4..b6222aad0 100644
--- a/app/vendor/composer/class-map-generator/src/PhpFileCleaner.php
+++ b/app/vendor/composer/class-map-generator/src/PhpFileCleaner.php
@@ -238,10 +238,11 @@ private function peek(string $char): bool
/**
* @param non-empty-string $regex
- * @param null|array $match
+ * @param null|array $match
+ * @param-out array $match
*/
- private function match(string $regex, array &$match = null): bool
+ private function match(string $regex, ?array &$match = null): bool
{
- return Preg::isMatch($regex, $this->contents, $match, 0, $this->index);
+ return Preg::isMatchStrictGroups($regex, $this->contents, $match, 0, $this->index);
}
}
diff --git a/app/vendor/composer/class-map-generator/src/PhpFileParser.php b/app/vendor/composer/class-map-generator/src/PhpFileParser.php
index b678aeee0..5a6875dce 100644
--- a/app/vendor/composer/class-map-generator/src/PhpFileParser.php
+++ b/app/vendor/composer/class-map-generator/src/PhpFileParser.php
@@ -24,12 +24,15 @@ class PhpFileParser
*
* @param string $path The file to check
* @throws \RuntimeException
- * @return array The found classes
+ * @return list The found classes
*/
public static function findClasses(string $path): array
{
$extraTypes = self::getExtraTypes();
+ if (!function_exists('php_strip_whitespace')) {
+ throw new \RuntimeException('Classmap generation relies on the php_strip_whitespace function, but it has been disabled by the disable_functions directive.');
+ }
// Use @ here instead of Silencer to actively suppress 'unhelpful' output
// @link https://github.com/composer/composer/pull/4886
$contents = @php_strip_whitespace($path);
@@ -63,8 +66,8 @@ public static function findClasses(string $path): array
Preg::matchAll('{
(?:
- \b(?])(?Pclass|interface|trait'.$extraTypes.') \s++ (?P[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
- | \b(?])(?Pnamespace) (?P\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]
+ \b(?])(?Pclass|interface|trait'.$extraTypes.') \s++ (?P[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
+ | \b(?])(?Pnamespace) (?P\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]
)
}ix', $contents, $matches);
@@ -98,7 +101,9 @@ public static function findClasses(string $path): array
$name = substr($name, 0, $colonPos);
}
}
- $classes[] = ltrim($namespace . $name, '\\');
+ /** @var class-string */
+ $className = ltrim($namespace . $name, '\\');
+ $classes[] = $className;
}
}
@@ -118,7 +123,10 @@ private static function getExtraTypes(): string
$extraTypes .= '|enum';
}
- PhpFileCleaner::setTypeConfig(array_merge(['class', 'interface', 'trait'], array_filter(explode('|', $extraTypes))));
+ $extraTypesArray = array_filter(explode('|', $extraTypes), function (string $type) {
+ return $type !== '';
+ });
+ PhpFileCleaner::setTypeConfig(array_merge(['class', 'interface', 'trait'], $extraTypesArray));
}
return $extraTypes;
diff --git a/app/vendor/composer/composer/bin/composer b/app/vendor/composer/composer/bin/composer
index 8bc77e660..4f6d08f72 100755
--- a/app/vendor/composer/composer/bin/composer
+++ b/app/vendor/composer/composer/bin/composer
@@ -42,7 +42,12 @@ if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
}
if (function_exists('ini_set')) {
- @ini_set('display_errors', '1');
+ // check if error logging is on, but to an empty destination - for the CLI SAPI, that means stderr
+ $logsToSapiDefault = ('' === ini_get('error_log') && (bool) ini_get('log_errors'));
+ // on the CLI SAPI, ensure errors are displayed on stderr, either via display_errors or via error_log
+ if (PHP_SAPI === 'cli') {
+ @ini_set('display_errors', $logsToSapiDefault ? '0' : 'stderr');
+ }
// Set user defined memory limit
if ($memoryLimit = getenv('COMPOSER_MEMORY_LIMIT')) {
diff --git a/app/vendor/composer/composer/composer.json b/app/vendor/composer/composer/composer.json
index 2cbcfa73d..2d6b132de 100644
--- a/app/vendor/composer/composer/composer.json
+++ b/app/vendor/composer/composer/composer.json
@@ -23,34 +23,34 @@
],
"require": {
"php": "^7.2.5 || ^8.0",
- "composer/ca-bundle": "^1.0",
- "composer/class-map-generator": "^1.0",
+ "composer/ca-bundle": "^1.5",
+ "composer/class-map-generator": "^1.4.0",
"composer/metadata-minifier": "^1.0",
- "composer/semver": "^3.2.5",
+ "composer/semver": "^3.3",
"composer/spdx-licenses": "^1.5.7",
"composer/xdebug-handler": "^2.0.2 || ^3.0.3",
- "justinrainbow/json-schema": "^5.2.11",
+ "justinrainbow/json-schema": "^6.3.1",
"psr/log": "^1.0 || ^2.0 || ^3.0",
"seld/jsonlint": "^1.4",
"seld/phar-utils": "^1.2",
- "symfony/console": "^5.4.11 || ^6.0.11 || ^7",
- "symfony/filesystem": "^5.4 || ^6.0 || ^7",
- "symfony/finder": "^5.4 || ^6.0 || ^7",
- "symfony/process": "^5.4 || ^6.0 || ^7",
- "react/promise": "^2.8 || ^3",
- "composer/pcre": "^2.1 || ^3.1",
+ "symfony/console": "^5.4.35 || ^6.3.12 || ^7.0.3",
+ "symfony/filesystem": "^5.4.35 || ^6.3.12 || ^7.0.3",
+ "symfony/finder": "^5.4.35 || ^6.3.12 || ^7.0.3",
+ "symfony/process": "^5.4.35 || ^6.3.12 || ^7.0.3",
+ "react/promise": "^2.11 || ^3.2",
+ "composer/pcre": "^2.2 || ^3.2",
"symfony/polyfill-php73": "^1.24",
"symfony/polyfill-php80": "^1.24",
"symfony/polyfill-php81": "^1.24",
"seld/signal-handler": "^2.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "^6.4.1 || ^7.0.1",
- "phpstan/phpstan": "^1.9.3",
- "phpstan/phpstan-phpunit": "^1.0",
- "phpstan/phpstan-deprecation-rules": "^1",
- "phpstan/phpstan-strict-rules": "^1",
- "phpstan/phpstan-symfony": "^1.2.10"
+ "symfony/phpunit-bridge": "^6.4.3 || ^7.0.1",
+ "phpstan/phpstan": "^1.11.8",
+ "phpstan/phpstan-phpunit": "^1.4.0",
+ "phpstan/phpstan-deprecation-rules": "^1.2.0",
+ "phpstan/phpstan-strict-rules": "^1.6.0",
+ "phpstan/phpstan-symfony": "^1.4.0"
},
"suggest": {
"ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
@@ -65,7 +65,7 @@
},
"extra": {
"branch-alias": {
- "dev-main": "2.7-dev"
+ "dev-main": "2.8-dev"
},
"phpstan": {
"includes": [
@@ -81,7 +81,13 @@
"autoload-dev": {
"psr-4": {
"Composer\\Test\\": "tests/Composer/Test/"
- }
+ },
+ "exclude-from-classmap": [
+ "tests/Composer/Test/Fixtures/",
+ "tests/Composer/Test/Autoload/Fixtures",
+ "tests/Composer/Test/Autoload/MinimumVersionSupport",
+ "tests/Composer/Test/Plugin/Fixtures"
+ ]
},
"bin": [
"bin/composer"
diff --git a/app/vendor/composer/composer/composer.lock b/app/vendor/composer/composer/composer.lock
index 2f1cd7693..abf0d4e3b 100644
--- a/app/vendor/composer/composer/composer.lock
+++ b/app/vendor/composer/composer/composer.lock
@@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "bbb9ffc97dcec54f38fdc5b4bf9a287d",
+ "content-hash": "346c859c80684f1cd23f57dc04f917b4",
"packages": [
{
"name": "composer/ca-bundle",
- "version": "1.5.0",
+ "version": "1.5.7",
"source": {
"type": "git",
"url": "https://github.com/composer/ca-bundle.git",
- "reference": "0c5ccfcfea312b5c5a190a21ac5cef93f74baf99"
+ "reference": "d665d22c417056996c59019579f1967dfe5c1e82"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/ca-bundle/zipball/0c5ccfcfea312b5c5a190a21ac5cef93f74baf99",
- "reference": "0c5ccfcfea312b5c5a190a21ac5cef93f74baf99",
+ "url": "https://api.github.com/repos/composer/ca-bundle/zipball/d665d22c417056996c59019579f1967dfe5c1e82",
+ "reference": "d665d22c417056996c59019579f1967dfe5c1e82",
"shasum": ""
},
"require": {
@@ -27,8 +27,8 @@
},
"require-dev": {
"phpstan/phpstan": "^1.10",
- "psr/log": "^1.0",
- "symfony/phpunit-bridge": "^4.2 || ^5",
+ "phpunit/phpunit": "^8 || ^9",
+ "psr/log": "^1.0 || ^2.0 || ^3.0",
"symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"type": "library",
@@ -64,7 +64,7 @@
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/ca-bundle/issues",
- "source": "https://github.com/composer/ca-bundle/tree/1.5.0"
+ "source": "https://github.com/composer/ca-bundle/tree/1.5.7"
},
"funding": [
{
@@ -80,20 +80,20 @@
"type": "tidelift"
}
],
- "time": "2024-03-15T14:00:32+00:00"
+ "time": "2025-05-26T15:08:54+00:00"
},
{
"name": "composer/class-map-generator",
- "version": "1.1.1",
+ "version": "1.6.1",
"source": {
"type": "git",
"url": "https://github.com/composer/class-map-generator.git",
- "reference": "8286a62d243312ed99b3eee20d5005c961adb311"
+ "reference": "134b705ddb0025d397d8318a75825fe3c9d1da34"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/class-map-generator/zipball/8286a62d243312ed99b3eee20d5005c961adb311",
- "reference": "8286a62d243312ed99b3eee20d5005c961adb311",
+ "url": "https://api.github.com/repos/composer/class-map-generator/zipball/134b705ddb0025d397d8318a75825fe3c9d1da34",
+ "reference": "134b705ddb0025d397d8318a75825fe3c9d1da34",
"shasum": ""
},
"require": {
@@ -102,12 +102,12 @@
"symfony/finder": "^4.4 || ^5.3 || ^6 || ^7"
},
"require-dev": {
- "phpstan/phpstan": "^1.6",
- "phpstan/phpstan-deprecation-rules": "^1",
- "phpstan/phpstan-phpunit": "^1",
- "phpstan/phpstan-strict-rules": "^1.1",
- "symfony/filesystem": "^5.4 || ^6",
- "symfony/phpunit-bridge": "^5"
+ "phpstan/phpstan": "^1.12 || ^2",
+ "phpstan/phpstan-deprecation-rules": "^1 || ^2",
+ "phpstan/phpstan-phpunit": "^1 || ^2",
+ "phpstan/phpstan-strict-rules": "^1.1 || ^2",
+ "phpunit/phpunit": "^8",
+ "symfony/filesystem": "^5.4 || ^6"
},
"type": "library",
"extra": {
@@ -137,7 +137,7 @@
],
"support": {
"issues": "https://github.com/composer/class-map-generator/issues",
- "source": "https://github.com/composer/class-map-generator/tree/1.1.1"
+ "source": "https://github.com/composer/class-map-generator/tree/1.6.1"
},
"funding": [
{
@@ -153,7 +153,7 @@
"type": "tidelift"
}
],
- "time": "2024-03-15T12:53:41+00:00"
+ "time": "2025-03-24T13:50:44+00:00"
},
{
"name": "composer/metadata-minifier",
@@ -226,28 +226,36 @@
},
{
"name": "composer/pcre",
- "version": "2.1.3",
+ "version": "2.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
- "reference": "540af382c97b83c628227d5f87cf56466d476191"
+ "reference": "ebb81df8f52b40172d14062ae96a06939d80a069"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/pcre/zipball/540af382c97b83c628227d5f87cf56466d476191",
- "reference": "540af382c97b83c628227d5f87cf56466d476191",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/ebb81df8f52b40172d14062ae96a06939d80a069",
+ "reference": "ebb81df8f52b40172d14062ae96a06939d80a069",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
+ "conflict": {
+ "phpstan/phpstan": "<1.11.10"
+ },
"require-dev": {
- "phpstan/phpstan": "^1.3",
- "phpstan/phpstan-strict-rules": "^1.1",
- "symfony/phpunit-bridge": "^5"
+ "phpstan/phpstan": "^1.12 || ^2",
+ "phpstan/phpstan-strict-rules": "^1 || ^2",
+ "phpunit/phpunit": "^8 || ^9"
},
"type": "library",
"extra": {
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ },
"branch-alias": {
"dev-main": "2.x-dev"
}
@@ -277,7 +285,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
- "source": "https://github.com/composer/pcre/tree/2.1.3"
+ "source": "https://github.com/composer/pcre/tree/2.3.2"
},
"funding": [
{
@@ -293,28 +301,28 @@
"type": "tidelift"
}
],
- "time": "2024-03-19T09:03:05+00:00"
+ "time": "2024-11-12T16:24:47+00:00"
},
{
"name": "composer/semver",
- "version": "3.4.0",
+ "version": "3.4.3",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
- "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
+ "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
- "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
+ "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
+ "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
- "phpstan/phpstan": "^1.4",
- "symfony/phpunit-bridge": "^4.2 || ^5"
+ "phpstan/phpstan": "^1.11",
+ "symfony/phpunit-bridge": "^3 || ^7"
},
"type": "library",
"extra": {
@@ -358,7 +366,7 @@
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
- "source": "https://github.com/composer/semver/tree/3.4.0"
+ "source": "https://github.com/composer/semver/tree/3.4.3"
},
"funding": [
{
@@ -374,28 +382,28 @@
"type": "tidelift"
}
],
- "time": "2023-08-31T09:50:34+00:00"
+ "time": "2024-09-19T14:15:21+00:00"
},
{
"name": "composer/spdx-licenses",
- "version": "1.5.8",
+ "version": "1.5.9",
"source": {
"type": "git",
"url": "https://github.com/composer/spdx-licenses.git",
- "reference": "560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a"
+ "reference": "edf364cefe8c43501e21e88110aac10b284c3c9f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a",
- "reference": "560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a",
+ "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/edf364cefe8c43501e21e88110aac10b284c3c9f",
+ "reference": "edf364cefe8c43501e21e88110aac10b284c3c9f",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
- "phpstan/phpstan": "^0.12.55",
- "symfony/phpunit-bridge": "^4.2 || ^5"
+ "phpstan/phpstan": "^1.11",
+ "symfony/phpunit-bridge": "^3 || ^7"
},
"type": "library",
"extra": {
@@ -438,7 +446,7 @@
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/spdx-licenses/issues",
- "source": "https://github.com/composer/spdx-licenses/tree/1.5.8"
+ "source": "https://github.com/composer/spdx-licenses/tree/1.5.9"
},
"funding": [
{
@@ -454,20 +462,20 @@
"type": "tidelift"
}
],
- "time": "2023-11-20T07:44:33+00:00"
+ "time": "2025-05-12T21:07:07+00:00"
},
{
"name": "composer/xdebug-handler",
- "version": "3.0.4",
+ "version": "3.0.5",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
- "reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255"
+ "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/4f988f8fdf580d53bdb2d1278fe93d1ed5462255",
- "reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef",
+ "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef",
"shasum": ""
},
"require": {
@@ -504,7 +512,7 @@
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
- "source": "https://github.com/composer/xdebug-handler/tree/3.0.4"
+ "source": "https://github.com/composer/xdebug-handler/tree/3.0.5"
},
"funding": [
{
@@ -520,29 +528,34 @@
"type": "tidelift"
}
],
- "time": "2024-03-26T18:29:49+00:00"
+ "time": "2024-05-06T16:37:16+00:00"
},
{
"name": "justinrainbow/json-schema",
- "version": "v5.2.13",
+ "version": "6.4.2",
"source": {
"type": "git",
- "url": "https://github.com/justinrainbow/json-schema.git",
- "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793"
+ "url": "https://github.com/jsonrainbow/json-schema.git",
+ "reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/fbbe7e5d79f618997bc3332a6f49246036c45793",
- "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793",
+ "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/ce1fd2d47799bb60668643bc6220f6278a4c1d02",
+ "reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "ext-json": "*",
+ "marc-mabe/php-enum": "^4.0",
+ "php": "^7.2 || ^8.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1",
+ "friendsofphp/php-cs-fixer": "3.3.0",
"json-schema/json-schema-test-suite": "1.2.0",
- "phpunit/phpunit": "^4.8.35"
+ "marc-mabe/php-enum-phpstan": "^2.0",
+ "phpspec/prophecy": "^1.19",
+ "phpstan/phpstan": "^1.12",
+ "phpunit/phpunit": "^8.5"
},
"bin": [
"bin/validate-json"
@@ -550,7 +563,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.0.x-dev"
+ "dev-master": "6.x-dev"
}
},
"autoload": {
@@ -581,16 +594,89 @@
}
],
"description": "A library to validate a json schema.",
- "homepage": "https://github.com/justinrainbow/json-schema",
+ "homepage": "https://github.com/jsonrainbow/json-schema",
"keywords": [
"json",
"schema"
],
"support": {
- "issues": "https://github.com/justinrainbow/json-schema/issues",
- "source": "https://github.com/justinrainbow/json-schema/tree/v5.2.13"
+ "issues": "https://github.com/jsonrainbow/json-schema/issues",
+ "source": "https://github.com/jsonrainbow/json-schema/tree/6.4.2"
},
- "time": "2023-09-26T02:20:38+00:00"
+ "time": "2025-06-03T18:27:04+00:00"
+ },
+ {
+ "name": "marc-mabe/php-enum",
+ "version": "v4.7.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/marc-mabe/php-enum.git",
+ "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/7159809e5cfa041dca28e61f7f7ae58063aae8ed",
+ "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed",
+ "shasum": ""
+ },
+ "require": {
+ "ext-reflection": "*",
+ "php": "^7.1 | ^8.0"
+ },
+ "require-dev": {
+ "phpbench/phpbench": "^0.16.10 || ^1.0.4",
+ "phpstan/phpstan": "^1.3.1",
+ "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11",
+ "vimeo/psalm": "^4.17.0 | ^5.26.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-3.x": "3.2-dev",
+ "dev-master": "4.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "MabeEnum\\": "src/"
+ },
+ "classmap": [
+ "stubs/Stringable.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Marc Bennewitz",
+ "email": "dev@mabe.berlin",
+ "homepage": "https://mabe.berlin/",
+ "role": "Lead"
+ }
+ ],
+ "description": "Simple and fast implementation of enumerations with native PHP",
+ "homepage": "https://github.com/marc-mabe/php-enum",
+ "keywords": [
+ "enum",
+ "enum-map",
+ "enum-set",
+ "enumeration",
+ "enumerator",
+ "enummap",
+ "enumset",
+ "map",
+ "set",
+ "type",
+ "type-hint",
+ "typehint"
+ ],
+ "support": {
+ "issues": "https://github.com/marc-mabe/php-enum/issues",
+ "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.1"
+ },
+ "time": "2024-11-28T04:54:44+00:00"
},
{
"name": "psr/container",
@@ -692,16 +778,16 @@
},
{
"name": "react/promise",
- "version": "v3.1.0",
+ "version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
- "reference": "e563d55d1641de1dea9f5e84f3cccc66d2bfe02c"
+ "reference": "8a164643313c71354582dc850b42b33fa12a4b63"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/reactphp/promise/zipball/e563d55d1641de1dea9f5e84f3cccc66d2bfe02c",
- "reference": "e563d55d1641de1dea9f5e84f3cccc66d2bfe02c",
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63",
+ "reference": "8a164643313c71354582dc850b42b33fa12a4b63",
"shasum": ""
},
"require": {
@@ -753,7 +839,7 @@
],
"support": {
"issues": "https://github.com/reactphp/promise/issues",
- "source": "https://github.com/reactphp/promise/tree/v3.1.0"
+ "source": "https://github.com/reactphp/promise/tree/v3.2.0"
},
"funding": [
{
@@ -761,27 +847,27 @@
"type": "open_collective"
}
],
- "time": "2023-11-16T16:21:57+00:00"
+ "time": "2024-05-24T10:39:05+00:00"
},
{
"name": "seld/jsonlint",
- "version": "1.10.2",
+ "version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/jsonlint.git",
- "reference": "9bb7db07b5d66d90f6ebf542f09fc67d800e5259"
+ "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9bb7db07b5d66d90f6ebf542f09fc67d800e5259",
- "reference": "9bb7db07b5d66d90f6ebf542f09fc67d800e5259",
+ "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2",
+ "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2",
"shasum": ""
},
"require": {
"php": "^5.3 || ^7.0 || ^8.0"
},
"require-dev": {
- "phpstan/phpstan": "^1.5",
+ "phpstan/phpstan": "^1.11",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13"
},
"bin": [
@@ -813,7 +899,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/jsonlint/issues",
- "source": "https://github.com/Seldaek/jsonlint/tree/1.10.2"
+ "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0"
},
"funding": [
{
@@ -825,7 +911,7 @@
"type": "tidelift"
}
],
- "time": "2024-02-07T12:57:50+00:00"
+ "time": "2024-07-11T14:55:45+00:00"
},
{
"name": "seld/phar-utils",
@@ -938,16 +1024,16 @@
},
{
"name": "symfony/console",
- "version": "v5.4.36",
+ "version": "v5.4.47",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e"
+ "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e",
- "reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e",
+ "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed",
+ "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed",
"shasum": ""
},
"require": {
@@ -1017,7 +1103,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v5.4.36"
+ "source": "https://github.com/symfony/console/tree/v5.4.47"
},
"funding": [
{
@@ -1033,20 +1119,20 @@
"type": "tidelift"
}
],
- "time": "2024-02-20T16:33:57+00:00"
+ "time": "2024-11-06T11:30:55+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v2.5.3",
+ "version": "v2.5.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "80d075412b557d41002320b96a096ca65aa2c98d"
+ "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/80d075412b557d41002320b96a096ca65aa2c98d",
- "reference": "80d075412b557d41002320b96a096ca65aa2c98d",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918",
+ "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918",
"shasum": ""
},
"require": {
@@ -1054,12 +1140,12 @@
},
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
"dev-main": "2.5-dev"
- },
- "thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -1084,7 +1170,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.3"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4"
},
"funding": [
{
@@ -1100,20 +1186,20 @@
"type": "tidelift"
}
],
- "time": "2023-01-24T14:02:46+00:00"
+ "time": "2024-09-25T14:11:13+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v5.4.38",
+ "version": "v5.4.45",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "899330a01056077271e2f614c7b28b0379a671eb"
+ "reference": "57c8294ed37d4a055b77057827c67f9558c95c54"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/899330a01056077271e2f614c7b28b0379a671eb",
- "reference": "899330a01056077271e2f614c7b28b0379a671eb",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/57c8294ed37d4a055b77057827c67f9558c95c54",
+ "reference": "57c8294ed37d4a055b77057827c67f9558c95c54",
"shasum": ""
},
"require": {
@@ -1122,6 +1208,9 @@
"symfony/polyfill-mbstring": "~1.8",
"symfony/polyfill-php80": "^1.16"
},
+ "require-dev": {
+ "symfony/process": "^5.4|^6.4"
+ },
"type": "library",
"autoload": {
"psr-4": {
@@ -1148,7 +1237,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v5.4.38"
+ "source": "https://github.com/symfony/filesystem/tree/v5.4.45"
},
"funding": [
{
@@ -1164,20 +1253,20 @@
"type": "tidelift"
}
],
- "time": "2024-03-21T08:05:07+00:00"
+ "time": "2024-10-22T13:05:35+00:00"
},
{
"name": "symfony/finder",
- "version": "v5.4.35",
+ "version": "v5.4.45",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "abe6d6f77d9465fed3cd2d029b29d03b56b56435"
+ "reference": "63741784cd7b9967975eec610b256eed3ede022b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/abe6d6f77d9465fed3cd2d029b29d03b56b56435",
- "reference": "abe6d6f77d9465fed3cd2d029b29d03b56b56435",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/63741784cd7b9967975eec610b256eed3ede022b",
+ "reference": "63741784cd7b9967975eec610b256eed3ede022b",
"shasum": ""
},
"require": {
@@ -1211,7 +1300,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v5.4.35"
+ "source": "https://github.com/symfony/finder/tree/v5.4.45"
},
"funding": [
{
@@ -1227,24 +1316,24 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T13:51:25+00:00"
+ "time": "2024-09-28T13:32:08+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.29.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4"
+ "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4",
- "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
+ "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.2"
},
"provide": {
"ext-ctype": "*"
@@ -1255,8 +1344,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -1290,7 +1379,7 @@
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0"
},
"funding": [
{
@@ -1306,24 +1395,24 @@
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
- "version": "v1.29.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
- "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f"
+ "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f",
- "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
+ "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.2"
},
"suggest": {
"ext-intl": "For best performance"
@@ -1331,8 +1420,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -1368,7 +1457,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0"
},
"funding": [
{
@@ -1384,24 +1473,24 @@
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.29.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
- "reference": "bc45c394692b948b4d383a08d7753968bed9a83d"
+ "reference": "3833d7255cc303546435cb650316bff708a1c75c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d",
- "reference": "bc45c394692b948b4d383a08d7753968bed9a83d",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
+ "reference": "3833d7255cc303546435cb650316bff708a1c75c",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.2"
},
"suggest": {
"ext-intl": "For best performance"
@@ -1409,8 +1498,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -1449,7 +1538,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0"
},
"funding": [
{
@@ -1465,24 +1554,25 @@
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.29.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
- "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "ext-iconv": "*",
+ "php": ">=7.2"
},
"provide": {
"ext-mbstring": "*"
@@ -1493,8 +1583,8 @@
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -1529,7 +1619,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
},
"funding": [
{
@@ -1545,30 +1635,30 @@
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2024-12-23T08:48:59+00:00"
},
{
"name": "symfony/polyfill-php73",
- "version": "v1.29.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
- "reference": "21bd091060673a1177ae842c0ef8fe30893114d2"
+ "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2",
- "reference": "21bd091060673a1177ae842c0ef8fe30893114d2",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
+ "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -1605,7 +1695,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php73/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-php73/tree/v1.32.0"
},
"funding": [
{
@@ -1621,30 +1711,30 @@
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php80",
- "version": "v1.29.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b"
+ "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
- "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+ "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -1685,7 +1775,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0"
},
"funding": [
{
@@ -1701,30 +1791,30 @@
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2025-01-02T08:10:11+00:00"
},
{
"name": "symfony/polyfill-php81",
- "version": "v1.29.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
- "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d"
+ "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/c565ad1e63f30e7477fc40738343c62b40bc672d",
- "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d",
+ "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
+ "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
@@ -1761,7 +1851,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php81/tree/v1.29.0"
+ "source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0"
},
"funding": [
{
@@ -1777,20 +1867,20 @@
"type": "tidelift"
}
],
- "time": "2024-01-29T20:11:03+00:00"
+ "time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/process",
- "version": "v5.4.36",
+ "version": "v5.4.47",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "4fdf34004f149cc20b2f51d7d119aa500caad975"
+ "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/4fdf34004f149cc20b2f51d7d119aa500caad975",
- "reference": "4fdf34004f149cc20b2f51d7d119aa500caad975",
+ "url": "https://api.github.com/repos/symfony/process/zipball/5d1662fb32ebc94f17ddb8d635454a776066733d",
+ "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d",
"shasum": ""
},
"require": {
@@ -1823,7 +1913,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v5.4.36"
+ "source": "https://github.com/symfony/process/tree/v5.4.47"
},
"funding": [
{
@@ -1839,20 +1929,20 @@
"type": "tidelift"
}
],
- "time": "2024-02-12T15:49:53+00:00"
+ "time": "2024-11-06T11:36:42+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v2.5.3",
+ "version": "v2.5.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3"
+ "reference": "f37b419f7aea2e9abf10abd261832cace12e3300"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a2329596ddc8fd568900e3fc76cba42489ecc7f3",
- "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300",
+ "reference": "f37b419f7aea2e9abf10abd261832cace12e3300",
"shasum": ""
},
"require": {
@@ -1868,12 +1958,12 @@
},
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
"dev-main": "2.5-dev"
- },
- "thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -1906,7 +1996,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v2.5.3"
+ "source": "https://github.com/symfony/service-contracts/tree/v2.5.4"
},
"funding": [
{
@@ -1922,20 +2012,20 @@
"type": "tidelift"
}
],
- "time": "2023-04-21T15:04:16+00:00"
+ "time": "2024-09-25T14:11:13+00:00"
},
{
"name": "symfony/string",
- "version": "v5.4.36",
+ "version": "v5.4.47",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "4e232c83622bd8cd32b794216aa29d0d266d353b"
+ "reference": "136ca7d72f72b599f2631aca474a4f8e26719799"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/4e232c83622bd8cd32b794216aa29d0d266d353b",
- "reference": "4e232c83622bd8cd32b794216aa29d0d266d353b",
+ "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799",
+ "reference": "136ca7d72f72b599f2631aca474a4f8e26719799",
"shasum": ""
},
"require": {
@@ -1992,7 +2082,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v5.4.36"
+ "source": "https://github.com/symfony/string/tree/v5.4.47"
},
"funding": [
{
@@ -2008,22 +2098,22 @@
"type": "tidelift"
}
],
- "time": "2024-02-01T08:49:30+00:00"
+ "time": "2024-11-10T20:33:58+00:00"
}
],
"packages-dev": [
{
"name": "phpstan/phpstan",
- "version": "1.10.67",
+ "version": "1.12.27",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493"
+ "reference": "3a6e423c076ab39dfedc307e2ac627ef579db162"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/16ddbe776f10da6a95ebd25de7c1dbed397dc493",
- "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3a6e423c076ab39dfedc307e2ac627ef579db162",
+ "reference": "3a6e423c076ab39dfedc307e2ac627ef579db162",
"shasum": ""
},
"require": {
@@ -2068,29 +2158,28 @@
"type": "github"
}
],
- "time": "2024-04-16T07:22:02+00:00"
+ "time": "2025-05-21T20:51:45+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
- "version": "1.1.4",
+ "version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-deprecation-rules.git",
- "reference": "089d8a8258ed0aeefdc7b68b6c3d25572ebfdbaa"
+ "reference": "f94d246cc143ec5a23da868f8f7e1393b50eaa82"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/089d8a8258ed0aeefdc7b68b6c3d25572ebfdbaa",
- "reference": "089d8a8258ed0aeefdc7b68b6c3d25572ebfdbaa",
+ "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/f94d246cc143ec5a23da868f8f7e1393b50eaa82",
+ "reference": "f94d246cc143ec5a23da868f8f7e1393b50eaa82",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
- "phpstan/phpstan": "^1.10.3"
+ "phpstan/phpstan": "^1.12"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
- "phpstan/phpstan-php-parser": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^9.5"
},
@@ -2114,27 +2203,27 @@
"description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.",
"support": {
"issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues",
- "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.1.4"
+ "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.2.1"
},
- "time": "2023-08-05T09:02:04+00:00"
+ "time": "2024-09-11T15:52:35+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
- "version": "1.3.16",
+ "version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
- "reference": "d5242a59d035e46774f2e634b374bc39ff62cb95"
+ "reference": "72a6721c9b64b3e4c9db55abbc38f790b318267e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/d5242a59d035e46774f2e634b374bc39ff62cb95",
- "reference": "d5242a59d035e46774f2e634b374bc39ff62cb95",
+ "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/72a6721c9b64b3e4c9db55abbc38f790b318267e",
+ "reference": "72a6721c9b64b3e4c9db55abbc38f790b318267e",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
- "phpstan/phpstan": "^1.10"
+ "phpstan/phpstan": "^1.12"
},
"conflict": {
"phpunit/phpunit": "<7.0"
@@ -2166,27 +2255,27 @@
"description": "PHPUnit extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
- "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.16"
+ "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.4.2"
},
- "time": "2024-02-23T09:51:20+00:00"
+ "time": "2024-12-17T17:20:49+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
- "version": "1.5.5",
+ "version": "1.6.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
- "reference": "2e193a07651a6f4be3baa44ddb21d822681f5918"
+ "reference": "b564ca479e7e735f750aaac4935af965572a7845"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/2e193a07651a6f4be3baa44ddb21d822681f5918",
- "reference": "2e193a07651a6f4be3baa44ddb21d822681f5918",
+ "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b564ca479e7e735f750aaac4935af965572a7845",
+ "reference": "b564ca479e7e735f750aaac4935af965572a7845",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
- "phpstan/phpstan": "^1.10.60"
+ "phpstan/phpstan": "^1.12.4"
},
"require-dev": {
"nikic/php-parser": "^4.13.0",
@@ -2215,28 +2304,28 @@
"description": "Extra strict and opinionated rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
- "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.5"
+ "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.2"
},
- "time": "2024-04-19T15:12:26+00:00"
+ "time": "2025-01-19T13:02:24+00:00"
},
{
"name": "phpstan/phpstan-symfony",
- "version": "1.3.12",
+ "version": "1.4.15",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-symfony.git",
- "reference": "f4b9407fa3203aebafd422ae8f0eb1ef94659a80"
+ "reference": "78b6b5a62f56731d938031c8f59817ed83b2328a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/f4b9407fa3203aebafd422ae8f0eb1ef94659a80",
- "reference": "f4b9407fa3203aebafd422ae8f0eb1ef94659a80",
+ "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/78b6b5a62f56731d938031c8f59817ed83b2328a",
+ "reference": "78b6b5a62f56731d938031c8f59817ed83b2328a",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"php": "^7.2 || ^8.0",
- "phpstan/phpstan": "^1.10.62"
+ "phpstan/phpstan": "^1.12"
},
"conflict": {
"symfony/framework-bundle": "<3.0"
@@ -2287,22 +2376,22 @@
"description": "Symfony Framework extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-symfony/issues",
- "source": "https://github.com/phpstan/phpstan-symfony/tree/1.3.12"
+ "source": "https://github.com/phpstan/phpstan-symfony/tree/1.4.15"
},
- "time": "2024-04-14T13:30:23+00:00"
+ "time": "2025-03-28T12:01:24+00:00"
},
{
"name": "symfony/phpunit-bridge",
- "version": "v7.0.6",
+ "version": "v7.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/phpunit-bridge.git",
- "reference": "a014167aa1f66cb9990675840da65609d3e61612"
+ "reference": "2eabda563921f21cbce1d1e3247b3c36568905e6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/a014167aa1f66cb9990675840da65609d3e61612",
- "reference": "a014167aa1f66cb9990675840da65609d3e61612",
+ "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/2eabda563921f21cbce1d1e3247b3c36568905e6",
+ "reference": "2eabda563921f21cbce1d1e3247b3c36568905e6",
"shasum": ""
},
"require": {
@@ -2322,8 +2411,8 @@
"type": "symfony-bridge",
"extra": {
"thanks": {
- "name": "phpunit/phpunit",
- "url": "https://github.com/sebastianbergmann/phpunit"
+ "url": "https://github.com/sebastianbergmann/phpunit",
+ "name": "phpunit/phpunit"
}
},
"autoload": {
@@ -2334,7 +2423,8 @@
"Symfony\\Bridge\\PhpUnit\\": ""
},
"exclude-from-classmap": [
- "/Tests/"
+ "/Tests/",
+ "/bin/"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -2354,7 +2444,7 @@
"description": "Provides utilities for PHPUnit, especially user deprecation notices management",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.6"
+ "source": "https://github.com/symfony/phpunit-bridge/tree/v7.3.0"
},
"funding": [
{
@@ -2370,18 +2460,18 @@
"type": "tidelift"
}
],
- "time": "2024-03-19T11:57:22+00:00"
+ "time": "2025-05-23T07:26:30+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "^7.2.5 || ^8.0"
},
- "platform-dev": [],
+ "platform-dev": {},
"platform-overrides": {
"php": "7.2.5"
},
diff --git a/app/vendor/composer/composer/res/composer-lock-schema.json b/app/vendor/composer/composer/res/composer-lock-schema.json
new file mode 100644
index 000000000..b1ef31c2b
--- /dev/null
+++ b/app/vendor/composer/composer/res/composer-lock-schema.json
@@ -0,0 +1,101 @@
+{
+ "$schema": "https://json-schema.org/draft-04/schema#",
+ "title": "Composer Lock File",
+ "type": "object",
+ "required": [ "content-hash", "packages", "packages-dev" ],
+ "additionalProperties": true,
+ "properties": {
+ "_readme": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Informational text for humans reading the file"
+ },
+ "content-hash": {
+ "type": "string",
+ "description": "Hash of all relevant properties of the composer.json that was used to create this lock file."
+ },
+ "packages": {
+ "type": "array",
+ "description": "An array of packages that are required.",
+ "items": {
+ "$ref": "./composer-schema.json",
+ "required": ["name", "version"]
+ }
+ },
+ "packages-dev": {
+ "type": "array",
+ "description": "An array of packages that are required in require-dev.",
+ "items": {
+ "$ref": "./composer-schema.json"
+ }
+ },
+ "aliases": {
+ "type": "array",
+ "description": "Inline aliases defined in the root package.",
+ "items": {
+ "type": "object",
+ "required": [ "package", "version", "alias", "alias_normalized" ],
+ "properties": {
+ "package": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "alias": {
+ "type": "string"
+ },
+ "alias_normalized": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "minimum-stability": {
+ "type": "string",
+ "description": "The minimum-stability used to generate this lock file."
+ },
+ "stability-flags": {
+ "type": "object",
+ "description": "Root package stability flags changing the minimum-stability for specific packages.",
+ "additionalProperties": {
+ "type": "integer"
+ }
+ },
+ "prefer-stable": {
+ "type": "boolean",
+ "description": "Whether the --prefer-stable flag was used when building this lock file."
+ },
+ "prefer-lowest": {
+ "type": "boolean",
+ "description": "Whether the --prefer-lowest flag was used when building this lock file."
+ },
+ "platform": {
+ "type": "object",
+ "description": "Platform requirements of the root package.",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "platform-dev": {
+ "type": "object",
+ "description": "Platform dev-requirements of the root package.",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "platform-overrides": {
+ "type": "object",
+ "description": "Platform config overrides of the root package.",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "plugin-api-version": {
+ "type": "string",
+ "description": "The composer-plugin-api version that was used to generate this lock file."
+ }
+ }
+}
diff --git a/app/vendor/composer/composer/res/composer-repository-schema.json b/app/vendor/composer/composer/res/composer-repository-schema.json
index adcc299d6..223f63abf 100644
--- a/app/vendor/composer/composer/res/composer-repository-schema.json
+++ b/app/vendor/composer/composer/res/composer-repository-schema.json
@@ -1,11 +1,12 @@
{
"$schema": "https://json-schema.org/draft-04/schema#",
- "description": "A representation of packages metadata.",
+ "title": "Composer Package Repository",
"type": "object",
"oneOf": [
{ "required": [ "packages" ] },
{ "required": [ "providers" ] },
- { "required": [ "provider-includes", "providers-url" ] }
+ { "required": [ "provider-includes", "providers-url" ] },
+ { "required": [ "metadata-url" ] }
],
"properties": {
"packages": {
@@ -13,31 +14,124 @@
"description": "A hashmap of package names in the form of /.",
"additionalProperties": { "$ref": "#/definitions/versions" }
},
+ "metadata-url": {
+ "type": "string",
+ "description": "Endpoint to retrieve package metadata data from, in Composer v2 format, e.g. '/p2/%package%.json'."
+ },
+ "available-packages": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "If your repository only has a small number of packages, and you want to avoid serving many 404s, specify all the package names that your repository contains here."
+ },
+ "available-package-patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "If your repository only has a small number of packages, and you want to avoid serving many 404s, specify package name patterns containing wildcards (*) that your repository contains here."
+ },
+ "security-advisories": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["metadata", "api-url"],
+ "properties": {
+ "metadata": {
+ "type": "boolean",
+ "description": "Whether metadata files contain security advisory data or whether it should always be queried using the API URL."
+ },
+ "api-url": {
+ "type": "string",
+ "description": "Endpoint to call to retrieve security advisories data."
+ }
+ }
+ }
+ },
+ "metadata-changes-url": {
+ "type": "string",
+ "description": "Endpoint to retrieve package metadata updates from. This should receive a timestamp since last call to be able to return new changes. e.g. '/metadata/changes.json'."
+ },
+ "providers-api": {
+ "type": "string",
+ "description": "Endpoint to retrieve package names providing a given name from, e.g. '/providers/%package%.json'."
+ },
+ "notify-batch": {
+ "type": "string",
+ "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
+ },
+ "search": {
+ "type": "string",
+ "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
+ },
+ "list": {
+ "type": "string",
+ "description": "Endpoint that provides a full list of packages present in the repository. It should accept an optional `?filter=xx` query param, which can contain `*` as wildcards matching any substring. e.g. '/list.json'."
+ },
+ "warnings": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["message", "versions"],
+ "properties": {
+ "message": {
+ "type": "string",
+ "description": "A message that will be output by Composer as a warning when this source is consulted."
+ },
+ "versions": {
+ "type": "string",
+ "description": "A version constraint to limit to which Composer versions the warning should be shown."
+ }
+ }
+ }
+ },
+ "infos": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["message", "versions"],
+ "properties": {
+ "message": {
+ "type": "string",
+ "description": "A message that will be output by Composer as info when this source is consulted."
+ },
+ "versions": {
+ "type": "string",
+ "description": "A version constraint to limit to which Composer versions the info should be shown."
+ }
+ }
+ }
+ },
"providers-url": {
"type": "string",
- "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
+ "description": "DEPRECATED: Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
},
"provider-includes": {
"type": "object",
- "description": "A hashmap of provider listings.",
+ "description": "DEPRECATED: A hashmap of provider listings.",
"additionalProperties": { "$ref": "#/definitions/provider" }
},
"providers": {
"type": "object",
- "description": "A hashmap of package names in the form of /.",
+ "description": "DEPRECATED: A hashmap of package names in the form of /.",
"additionalProperties": { "$ref": "#/definitions/provider" }
},
- "notify-batch": {
+ "warning": {
"type": "string",
- "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
+ "description": "DEPRECATED: A message that will be output by Composer as a warning when this source is consulted."
},
- "search": {
+ "warning-versions": {
"type": "string",
- "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
+ "description": "DEPRECATED: A version constraint to limit to which Composer versions the warning should be shown."
},
- "warning": {
+ "info": {
+ "type": "string",
+ "description": "DEPRECATED: A message that will be output by Composer as a info when this source is consulted."
+ },
+ "info-versions": {
"type": "string",
- "description": "A message that will be output by Composer as a warning when this source is consulted."
+ "description": "DEPRECATED: A version constraint to limit to which Composer versions the info should be shown."
}
},
"definitions": {
diff --git a/app/vendor/composer/composer/res/composer-schema.json b/app/vendor/composer/composer/res/composer-schema.json
index 90714875c..d8728e973 100644
--- a/app/vendor/composer/composer/res/composer-schema.json
+++ b/app/vendor/composer/composer/res/composer-schema.json
@@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft-04/schema#",
- "title": "Package",
+ "title": "Composer Package",
"type": "object",
"properties": {
"name": {
@@ -28,7 +28,7 @@
"version": {
"type": "string",
"description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.",
- "pattern": "^v?\\d+(\\.\\d+){0,3}|^dev-"
+ "pattern": "^[vV]?\\d+(?:[.-]\\d+){0,3}[._-]?(?:(?:[sS][tT][aA][bB][lL][eE]|[bB][eE][tT][aA]|[bB]|[rR][cC]|[aA][lL][pP][hH][aA]|[aA]|[pP][aA][tT][cC][hH]|[pP][lL]|[pP])(?:(?:[.-]?\\d+)*)?)?(?:[.-]?[dD][eE][vV]|\\.x-dev)?(?:\\+.*)?$|^dev-.*$"
},
"default-branch": {
"type": ["boolean"],
@@ -311,6 +311,44 @@
"example": false,
"default": true
},
+ "support-nts": {
+ "type": "boolean",
+ "description": "Does this package support non-Thread Safe mode",
+ "example": false,
+ "default": true
+ },
+ "build-path": {
+ "type": ["string", "null"],
+ "description": "If specified, this is the subdirectory that will be used to build the extension instead of the root of the project.",
+ "example": "my-extension-source",
+ "default": null
+ },
+ "download-url-method": {
+ "type": "string",
+ "description": "If specified, this technique will be used to override the URL that PIE uses to download the asset. The default, if not specified, is composer-default.",
+ "enum": ["composer-default", "pre-packaged-source"],
+ "example": "composer-default"
+ },
+ "os-families": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An array of OS families to mark as compatible with the extension. Specifying this property will mean this package is not installable with PIE on any OS family not listed here. Must not be specified alongside os-families-exclude.",
+ "items": {
+ "type": "string",
+ "enum": ["windows", "bsd", "darwin", "solaris", "linux", "unknown"],
+ "description": "The name of the OS family to mark as compatible."
+ }
+ },
+ "os-families-exclude": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An array of OS families to mark as incompatible with the extension. Specifying this property will mean this package is installable on any OS family except those listed here. Must not be specified alongside os-families.",
+ "items": {
+ "type": "string",
+ "enum": ["windows", "bsd", "darwin", "solaris", "linux", "unknown"],
+ "description": "The name of the OS family to exclude."
+ }
+ },
"configure-options": {
"type": "array",
"description": "These configure options make up the flags that can be passed to ./configure when installing the extension.",
@@ -324,6 +362,12 @@
"example": "without-xdebug-compression",
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]*$"
},
+ "needs-value": {
+ "type": "boolean",
+ "description": "If this is set to true, the flag needs a value (e.g. --with-somelib=), otherwise it is a flag without a value (e.g. --enable-some-feature).",
+ "example": false,
+ "default": false
+ },
"description": {
"type": "string",
"description": "The description of what the flag does or means.",
@@ -332,7 +376,14 @@
}
}
}
- }
+ },
+ "allOf": [
+ {
+ "not": {
+ "required": ["os-families", "os-families-exclude"]
+ }
+ }
+ ]
},
"config": {
"type": "object",
@@ -656,6 +707,14 @@
"platform-check": {
"type": ["boolean", "string"],
"description": "Defaults to \"php-only\" which checks only the PHP version. Setting to true will also check the presence of required PHP extensions. If set to false, Composer will not create and require a platform_check.php file as part of the autoloader bootstrap."
+ },
+ "bump-after-update": {
+ "type": ["string", "boolean"],
+ "description": "Defaults to false and can be any of true, false, \"dev\"` or \"no-dev\"`. If set to true, Composer will run the bump command after running the update command. If set to \"dev\" or \"no-dev\" then only the corresponding dependencies will be bumped."
+ },
+ "allow-missing-requirements": {
+ "type": ["boolean"],
+ "description": "Defaults to false. If set to true, Composer will allow install when lock file is not up to date with the latest changes in composer.json."
}
}
},
@@ -910,7 +969,10 @@
"options": {
"type": "object",
"properties": {
- "symlink": { "type": ["boolean", "null"] }
+ "reference": { "type": ["string"], "enum": ["none", "config", "auto"] },
+ "symlink": { "type": ["boolean", "null"] },
+ "relative": { "type": ["boolean"] },
+ "versions": { "type": "object", "additionalProperties": { "type": "string" } }
},
"additionalProperties": true
}
diff --git a/app/vendor/composer/composer/src/Composer/Advisory/Auditor.php b/app/vendor/composer/composer/src/Composer/Advisory/Auditor.php
index 38d827dfe..485b33267 100644
--- a/app/vendor/composer/composer/src/Composer/Advisory/Auditor.php
+++ b/app/vendor/composer/composer/src/Composer/Advisory/Auditor.php
@@ -19,7 +19,6 @@
use Composer\Package\PackageInterface;
use Composer\Repository\RepositorySet;
use Composer\Util\PackageInfo;
-use Composer\Util\Platform;
use InvalidArgumentException;
use Symfony\Component\Console\Formatter\OutputFormatter;
@@ -47,17 +46,30 @@ class Auditor
public const ABANDONED_REPORT = 'report';
public const ABANDONED_FAIL = 'fail';
+ /** @internal */
+ public const ABANDONEDS = [
+ self::ABANDONED_IGNORE,
+ self::ABANDONED_REPORT,
+ self::ABANDONED_FAIL,
+ ];
+
+ /** Values to determine the audit result. */
+ public const STATUS_OK = 0;
+ public const STATUS_VULNERABLE = 1;
+ public const STATUS_ABANDONED = 2;
+
/**
* @param PackageInterface[] $packages
* @param self::FORMAT_* $format The format that will be used to output audit results.
* @param bool $warningOnly If true, outputs a warning. If false, outputs an error.
* @param string[] $ignoreList List of advisory IDs, remote IDs or CVE IDs that reported but not listed as vulnerabilities.
* @param self::ABANDONED_* $abandoned
+ * @param array $ignoredSeverities List of ignored severity levels
*
- * @return int Amount of packages with vulnerabilities found
+ * @return int-mask A bitmask of STATUS_* constants or 0 on success
* @throws InvalidArgumentException If no packages are passed in
*/
- public function audit(IOInterface $io, RepositorySet $repoSet, array $packages, string $format, bool $warningOnly = true, array $ignoreList = [], string $abandoned = self::ABANDONED_FAIL): int
+ public function audit(IOInterface $io, RepositorySet $repoSet, array $packages, string $format, bool $warningOnly = true, array $ignoreList = [], string $abandoned = self::ABANDONED_FAIL, array $ignoredSeverities = []): int
{
$allAdvisories = $repoSet->getMatchingSecurityAdvisories($packages, $format === self::FORMAT_SUMMARY);
// we need the CVE & remote IDs set to filter ignores correctly so if we have any matches using the optimized codepath above
@@ -65,10 +77,10 @@ public function audit(IOInterface $io, RepositorySet $repoSet, array $packages,
if (count($allAdvisories) > 0 && $ignoreList !== [] && $format === self::FORMAT_SUMMARY) {
$allAdvisories = $repoSet->getMatchingSecurityAdvisories($packages, false);
}
- ['advisories' => $advisories, 'ignoredAdvisories' => $ignoredAdvisories] = $this->processAdvisories($allAdvisories, $ignoreList);
+ ['advisories' => $advisories, 'ignoredAdvisories' => $ignoredAdvisories] = $this->processAdvisories($allAdvisories, $ignoreList, $ignoredSeverities);
$abandonedCount = 0;
- $affectedPackagesCount = 0;
+ $affectedPackagesCount = count($advisories);
if ($abandoned === self::ABANDONED_IGNORE) {
$abandonedPackages = [];
} else {
@@ -78,35 +90,37 @@ public function audit(IOInterface $io, RepositorySet $repoSet, array $packages,
}
}
+ $auditBitmask = $this->calculateBitmask(0 < $affectedPackagesCount, 0 < $abandonedCount);
+
if (self::FORMAT_JSON === $format) {
$json = ['advisories' => $advisories];
if ($ignoredAdvisories !== []) {
$json['ignored-advisories'] = $ignoredAdvisories;
}
- $json['abandoned'] = array_reduce($abandonedPackages, static function(array $carry, CompletePackageInterface $package): array {
+ $json['abandoned'] = array_reduce($abandonedPackages, static function (array $carry, CompletePackageInterface $package): array {
$carry[$package->getPrettyName()] = $package->getReplacementPackage();
+
return $carry;
}, []);
$io->write(JsonFile::encode($json));
- return count($advisories) + $abandonedCount;
+ return $auditBitmask;
}
$errorOrWarn = $warningOnly ? 'warning' : 'error';
- if (count($advisories) > 0 || count($ignoredAdvisories) > 0) {
+ if ($affectedPackagesCount > 0 || count($ignoredAdvisories) > 0) {
$passes = [
[$ignoredAdvisories, "Found %d ignored security vulnerability advisor%s affecting %d package%s%s"],
- // this has to run last to allow $affectedPackagesCount in the return statement to be correct
[$advisories, "<$errorOrWarn>Found %d security vulnerability advisor%s affecting %d package%s%s$errorOrWarn>"],
];
foreach ($passes as [$advisoriesToOutput, $message]) {
- [$affectedPackagesCount, $totalAdvisoryCount] = $this->countAdvisories($advisoriesToOutput);
- if ($affectedPackagesCount > 0) {
+ [$pkgCount, $totalAdvisoryCount] = $this->countAdvisories($advisoriesToOutput);
+ if ($pkgCount > 0) {
$plurality = $totalAdvisoryCount === 1 ? 'y' : 'ies';
- $pkgPlurality = $affectedPackagesCount === 1 ? '' : 's';
+ $pkgPlurality = $pkgCount === 1 ? '' : 's';
$punctuation = $format === 'summary' ? '.' : ':';
- $io->writeError(sprintf($message, $totalAdvisoryCount, $plurality, $affectedPackagesCount, $pkgPlurality, $punctuation));
+ $io->writeError(sprintf($message, $totalAdvisoryCount, $plurality, $pkgCount, $pkgPlurality, $punctuation));
$this->outputAdvisories($io, $advisoriesToOutput, $format);
}
}
@@ -122,7 +136,7 @@ public function audit(IOInterface $io, RepositorySet $repoSet, array $packages,
$this->outputAbandonedPackages($io, $abandonedPackages, $format);
}
- return $affectedPackagesCount + $abandonedCount;
+ return $auditBitmask;
}
/**
@@ -131,7 +145,7 @@ public function audit(IOInterface $io, RepositorySet $repoSet, array $packages,
*/
private function filterAbandonedPackages(array $packages): array
{
- return array_filter($packages, static function (PackageInterface $pkg) {
+ return array_filter($packages, static function (PackageInterface $pkg): bool {
return $pkg instanceof CompletePackageInterface && $pkg->isAbandoned();
});
}
@@ -139,11 +153,12 @@ private function filterAbandonedPackages(array $packages): array
/**
* @phpstan-param array> $allAdvisories
* @param array|array $ignoreList List of advisory IDs, remote IDs or CVE IDs that reported but not listed as vulnerabilities.
+ * @param array $ignoredSeverities List of ignored severity levels
* @phpstan-return array{advisories: array>, ignoredAdvisories: array>}
*/
- private function processAdvisories(array $allAdvisories, array $ignoreList): array
+ private function processAdvisories(array $allAdvisories, array $ignoreList, array $ignoredSeverities): array
{
- if ($ignoreList === []) {
+ if ($ignoreList === [] && $ignoredSeverities === []) {
return ['advisories' => $allAdvisories, 'ignoredAdvisories' => []];
}
@@ -167,6 +182,11 @@ private function processAdvisories(array $allAdvisories, array $ignoreList): arr
}
if ($advisory instanceof SecurityAdvisory) {
+ if (in_array($advisory->severity, $ignoredSeverities, true)) {
+ $isActive = false;
+ $ignoreReason = "Ignored via --ignore-severity={$advisory->severity}";
+ }
+
if (in_array($advisory->cve, $ignoredIds, true)) {
$isActive = false;
$ignoreReason = $ignoreList[$advisory->cve] ?? null;
@@ -388,4 +408,21 @@ private function getURL(SecurityAdvisory $advisory): string
return 'link).'>'.OutputFormatter::escape($advisory->link).'>';
}
+ /**
+ * @return int-mask
+ */
+ private function calculateBitmask(bool $hasVulnerablePackages, bool $hasAbandonedPackages): int
+ {
+ $bitmask = self::STATUS_OK;
+
+ if ($hasVulnerablePackages) {
+ $bitmask |= self::STATUS_VULNERABLE;
+ }
+
+ if ($hasAbandonedPackages) {
+ $bitmask |= self::STATUS_ABANDONED;
+ }
+
+ return $bitmask;
+ }
}
diff --git a/app/vendor/composer/composer/src/Composer/Autoload/AutoloadGenerator.php b/app/vendor/composer/composer/src/Composer/Autoload/AutoloadGenerator.php
index 844b80207..442228894 100644
--- a/app/vendor/composer/composer/src/Composer/Autoload/AutoloadGenerator.php
+++ b/app/vendor/composer/composer/src/Composer/Autoload/AutoloadGenerator.php
@@ -34,6 +34,7 @@
use Composer\Util\PackageSorter;
use Composer\Json\JsonFile;
use Composer\Package\Locker;
+use Symfony\Component\Console\Formatter\OutputFormatter;
/**
* @author Igor Wiedler
@@ -173,7 +174,7 @@ public function setPlatformRequirementFilter(PlatformRequirementFilterInterface
* @throws \Seld\JsonLint\ParsingException
* @throws \RuntimeException
*/
- public function dump(Config $config, InstalledRepositoryInterface $localRepo, RootPackageInterface $rootPackage, InstallationManager $installationManager, string $targetDir, bool $scanPsrPackages = false, ?string $suffix = null, ?Locker $locker = null)
+ public function dump(Config $config, InstalledRepositoryInterface $localRepo, RootPackageInterface $rootPackage, InstallationManager $installationManager, string $targetDir, bool $scanPsrPackages = false, ?string $suffix = null, ?Locker $locker = null, bool $strictAmbiguous = false)
{
if ($this->classMapAuthoritative) {
// Force scanPsrPackages when classmap is authoritative
@@ -319,7 +320,7 @@ public static function autoload(\$class)
EOF;
}
- $excluded = null;
+ $excluded = [];
if (!empty($autoloads['exclude-from-classmap'])) {
$excluded = $autoloads['exclude-from-classmap'];
}
@@ -348,14 +349,26 @@ public static function autoload(\$class)
continue;
}
- $classMapGenerator->scanPaths($dir, $this->buildExclusionRegex($dir, $excluded), $group['type'], $namespace);
+ // if the vendor dir is contained within a psr-0/psr-4 dir being scanned we exclude it
+ if (str_contains($vendorPath, $dir.'/')) {
+ $exclusionRegex = $this->buildExclusionRegex($dir, array_merge($excluded, [$vendorPath.'/']));
+ } else {
+ $exclusionRegex = $this->buildExclusionRegex($dir, $excluded);
+ }
+
+ $classMapGenerator->scanPaths($dir, $exclusionRegex, $group['type'], $namespace);
}
}
}
}
$classMap = $classMapGenerator->getClassMap();
- foreach ($classMap->getAmbiguousClasses() as $className => $ambiguousPaths) {
+ if ($strictAmbiguous) {
+ $ambiguousClasses = $classMap->getAmbiguousClasses(false);
+ } else {
+ $ambiguousClasses = $classMap->getAmbiguousClasses();
+ }
+ foreach ($ambiguousClasses as $className => $ambiguousPaths) {
if (count($ambiguousPaths) > 1) {
$this->io->writeError(
'Warning: Ambiguous class resolution, "'.$className.'"'.
@@ -368,6 +381,12 @@ public static function autoload(\$class)
);
}
}
+ if (\count($ambiguousClasses) > 0) {
+ $this->io->writeError('To resolve ambiguity in classes not under your control you can ignore them by path using exclude-from-classmap>');
+ }
+
+ // output PSR violations which are not coming from the vendor dir
+ $classMap->clearPsrViolationsByPath($vendorPath);
foreach ($classMap->getPsrViolations() as $msg) {
$this->io->writeError("$msg");
}
@@ -400,14 +419,14 @@ public static function autoload(\$class)
// carry over existing autoload.php's suffix if possible and none is configured
if (null === $suffix && Filesystem::isReadable($vendorPath.'/autoload.php')) {
- $content = file_get_contents($vendorPath.'/autoload.php');
+ $content = (string) file_get_contents($vendorPath.'/autoload.php');
if (Preg::isMatch('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
$suffix = $match[1];
}
}
if (null === $suffix) {
- $suffix = $locker !== null && $locker->isLocked() ? $locker->getLockData()['content-hash'] : md5(uniqid('', true));
+ $suffix = $locker !== null && $locker->isLocked() ? $locker->getLockData()['content-hash'] : bin2hex(random_bytes(16));
}
}
@@ -460,12 +479,12 @@ public static function autoload(\$class)
}
/**
- * @param array|null $excluded
+ * @param array $excluded
* @return non-empty-string|null
*/
- private function buildExclusionRegex(string $dir, ?array $excluded): ?string
+ private function buildExclusionRegex(string $dir, array $excluded): ?string
{
- if (null === $excluded) {
+ if ([] === $excluded) {
return null;
}
@@ -559,12 +578,17 @@ public function parseAutoloads(array $packageMap, PackageInterface $rootPackage,
}
$sortedPackageMap = $this->sortPackageMap($packageMap);
$sortedPackageMap[] = $rootPackageMap;
- array_unshift($packageMap, $rootPackageMap);
+ $reverseSortedMap = array_reverse($sortedPackageMap);
+
+ // reverse-sorted means root first, then dependents, then their dependents, etc.
+ // which makes sense to allow root to override classmap or psr-0/4 entries with higher precedence rules
+ $psr0 = $this->parseAutoloadsType($reverseSortedMap, 'psr-0', $rootPackage);
+ $psr4 = $this->parseAutoloadsType($reverseSortedMap, 'psr-4', $rootPackage);
+ $classmap = $this->parseAutoloadsType($reverseSortedMap, 'classmap', $rootPackage);
- $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $rootPackage);
- $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $rootPackage);
- $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $rootPackage);
+ // sorted (i.e. dependents first) for files to ensure that dependencies are loaded/available once a file is included
$files = $this->parseAutoloadsType($sortedPackageMap, 'files', $rootPackage);
+ // using sorted here but it does not really matter as all are excluded equally
$exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $rootPackage);
krsort($psr0);
@@ -602,7 +626,7 @@ public function createLoader(array $autoloads, ?string $vendorDir = null)
}
if (isset($autoloads['classmap'])) {
- $excluded = null;
+ $excluded = [];
if (!empty($autoloads['exclude-from-classmap'])) {
$excluded = $autoloads['exclude-from-classmap'];
}
@@ -646,11 +670,11 @@ protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem
foreach ($package->getIncludePaths() as $includePath) {
$includePath = trim($includePath, '/');
- $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
+ $includePaths[] = $installPath === '' ? $includePath : $installPath.'/'.$includePath;
}
}
- if (!$includePaths) {
+ if (\count($includePaths) === 0) {
return null;
}
@@ -741,7 +765,7 @@ protected function getPathCode(Filesystem $filesystem, string $basePath, string
}
}
- if (strpos($path, '.phar') !== false) {
+ if (Preg::isMatch('{\.phar([\\\\/]|$)}', $path)) {
$baseDir = "'phar://' . " . $baseDir;
}
@@ -913,9 +937,8 @@ protected function getPlatformCheck(array $packageMap, $checkPlatform, array $de
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, \$issues)) . PHP_EOL.PHP_EOL;
}
}
- trigger_error(
- 'Composer detected issues in your platform: ' . implode(' ', \$issues),
- E_USER_ERROR
+ throw new \RuntimeException(
+ 'Composer detected issues in your platform: ' . implode(' ', \$issues)
);
}
@@ -951,10 +974,7 @@ protected function getAutoloadFile(string $vendorPathToTargetDirCode, string $su
echo \$err;
}
}
- trigger_error(
- \$err,
- E_USER_ERROR
- );
+ throw new RuntimeException(\$err);
}
require_once $vendorPathToTargetDirCode;
@@ -1042,7 +1062,7 @@ public static function getLoader()
}
if ($this->apcu) {
- $apcuPrefix = var_export(($this->apcuPrefix !== null ? $this->apcuPrefix : substr(base64_encode(md5(uniqid('', true), true)), 0, -3)), true);
+ $apcuPrefix = var_export(($this->apcuPrefix !== null ? $this->apcuPrefix : bin2hex(random_bytes(10))), true);
$file .= <<setApcuPrefix($apcuPrefix);
@@ -1231,6 +1251,10 @@ protected function parseAutoloadsType(array $packageMap, string $type, RootPacka
}
foreach ($autoload[$type] as $namespace => $paths) {
+ if (in_array($type, ['psr-4', 'psr-0'], true)) {
+ // normalize namespaces to ensure "\" becomes "" and others do not have leading separators as they are not needed
+ $namespace = ltrim($namespace, '\\');
+ }
foreach ((array) $paths as $path) {
if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !Filesystem::isReadable($installPath.'/'.$path)) {
// remove target-dir from file paths of the root package
@@ -1255,10 +1279,8 @@ protected function parseAutoloadsType(array $packageMap, string $type, RootPacka
$path = Preg::replaceCallback(
'{^((?:(?:\\\\\\.){1,2}+/)+)}',
static function ($matches) use (&$updir): string {
- if (isset($matches[1])) {
- // undo preg_quote for the matched string
- $updir = str_replace('\\.', '.', $matches[1]);
- }
+ // undo preg_quote for the matched string
+ $updir = str_replace('\\.', '.', $matches[1]);
return '';
},
@@ -1300,7 +1322,8 @@ static function ($matches) use (&$updir): string {
*/
protected function getFileIdentifier(PackageInterface $package, string $path)
{
- return md5($package->getName() . ':' . $path);
+ // TODO composer v3 change this to sha1 or xxh3? Possibly not worth the potential breakage though
+ return hash('md5', $package->getName() . ':' . $path);
}
/**
diff --git a/app/vendor/composer/composer/src/Composer/Cache.php b/app/vendor/composer/composer/src/Composer/Cache.php
index 1a216c592..e18715f47 100644
--- a/app/vendor/composer/composer/src/Composer/Cache.php
+++ b/app/vendor/composer/composer/src/Composer/Cache.php
@@ -53,7 +53,7 @@ public function __construct(IOInterface $io, string $cacheDir, string $allowlist
$this->root = rtrim($cacheDir, '/\\') . '/';
$this->allowlist = $allowlist;
$this->filesystem = $filesystem ?: new Filesystem();
- $this->readOnly = (bool) $readOnly;
+ $this->readOnly = $readOnly;
if (!self::isUsable($cacheDir)) {
$this->enabled = false;
@@ -65,7 +65,7 @@ public function __construct(IOInterface $io, string $cacheDir, string $allowlist
*/
public function setReadOnly(bool $readOnly)
{
- $this->readOnly = (bool) $readOnly;
+ $this->readOnly = $readOnly;
}
/**
@@ -144,7 +144,7 @@ public function write(string $file, string $contents)
$this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
- $tempFileName = $this->root . $file . uniqid('.', true) . '.tmp';
+ $tempFileName = $this->root . $file . bin2hex(random_bytes(5)) . '.tmp';
try {
return file_put_contents($tempFileName, $contents) !== false && rename($tempFileName, $this->root . $file);
} catch (\ErrorException $e) {
@@ -198,7 +198,7 @@ public function copyFrom(string $file, string $source)
$this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
}
- return copy($source, $this->root . $file);
+ return $this->filesystem->copy($source, $this->root . $file);
}
return false;
@@ -224,7 +224,7 @@ public function copyTo(string $file, string $target)
$this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
- return copy($this->root . $file, $target);
+ return $this->filesystem->copy($this->root . $file, $target);
}
}
@@ -357,7 +357,7 @@ public function sha1(string $file)
if ($this->isEnabled()) {
$file = Preg::replace('{[^'.$this->allowlist.']}i', '-', $file);
if (file_exists($this->root . $file)) {
- return sha1_file($this->root . $file);
+ return hash_file('sha1', $this->root . $file);
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/ArchiveCommand.php b/app/vendor/composer/composer/src/Composer/Command/ArchiveCommand.php
index e0189109b..b71f4e241 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ArchiveCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ArchiveCommand.php
@@ -169,7 +169,7 @@ protected function selectPackage(IOInterface $io, string $packageName, ?string $
}
if ($version !== null && Preg::isMatchStrictGroups('{@(stable|RC|beta|alpha|dev)$}i', $version, $match)) {
- $minStability = $match[1];
+ $minStability = VersionParser::normalizeStability($match[1]);
$version = (string) substr($version, 0, -strlen($match[0]));
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/AuditCommand.php b/app/vendor/composer/composer/src/Composer/Command/AuditCommand.php
index 1097bb7af..e4a2094b8 100644
--- a/app/vendor/composer/composer/src/Composer/Command/AuditCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/AuditCommand.php
@@ -33,6 +33,8 @@ protected function configure(): void
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables auditing of require-dev packages.'),
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_TABLE, Auditor::FORMATS),
new InputOption('locked', null, InputOption::VALUE_NONE, 'Audit based on the lock file instead of the installed packages.'),
+ new InputOption('abandoned', null, InputOption::VALUE_REQUIRED, 'Behavior on abandoned packages. Must be "ignore", "report", or "fail".', null, Auditor::ABANDONEDS),
+ new InputOption('ignore-severity', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Ignore advisories of a certain severity level.', [], ['low', 'medium', 'high', 'critical']),
])
->setHelp(
<<getConfig()->get('audit');
- return min(255, $auditor->audit($this->getIO(), $repoSet, $packages, $this->getAuditFormat($input, 'format'), false, $auditConfig['ignore'] ?? [], $auditConfig['abandoned'] ?? Auditor::ABANDONED_FAIL));
+ $abandoned = $input->getOption('abandoned');
+ if ($abandoned !== null && !in_array($abandoned, Auditor::ABANDONEDS, true)) {
+ throw new \InvalidArgumentException('--audit must be one of '.implode(', ', Auditor::ABANDONEDS).'.');
+ }
+
+ $abandoned = $abandoned ?? $auditConfig['abandoned'] ?? Auditor::ABANDONED_FAIL;
+
+ $ignoreSeverities = $input->getOption('ignore-severity') ?? [];
+
+ return min(255, $auditor->audit(
+ $this->getIO(),
+ $repoSet,
+ $packages,
+ $this->getAuditFormat($input, 'format'),
+ false,
+ $auditConfig['ignore'] ?? [],
+ $abandoned,
+ $ignoreSeverities
+ ));
+
}
/**
diff --git a/app/vendor/composer/composer/src/Composer/Command/BaseCommand.php b/app/vendor/composer/composer/src/Composer/Command/BaseCommand.php
index bdfbb0d05..85c99f74b 100644
--- a/app/vendor/composer/composer/src/Composer/Command/BaseCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/BaseCommand.php
@@ -258,6 +258,8 @@ protected function initialize(InputInterface $input, OutputInterface $output)
'COMPOSER_PREFER_STABLE' => ['prefer-stable'],
'COMPOSER_PREFER_LOWEST' => ['prefer-lowest'],
'COMPOSER_MINIMAL_CHANGES' => ['minimal-changes'],
+ 'COMPOSER_WITH_DEPENDENCIES' => ['with-dependencies'],
+ 'COMPOSER_WITH_ALL_DEPENDENCIES' => ['with-all-dependencies'],
];
foreach ($envOptions as $envName => $optionNames) {
foreach ($optionNames as $optionName) {
diff --git a/app/vendor/composer/composer/src/Composer/Command/BaseDependencyCommand.php b/app/vendor/composer/composer/src/Composer/Command/BaseDependencyCommand.php
index 2fb363979..1f67f5bc3 100644
--- a/app/vendor/composer/composer/src/Composer/Command/BaseDependencyCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/BaseDependencyCommand.php
@@ -13,6 +13,7 @@
namespace Composer\Command;
use Composer\Package\Link;
+use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Package\CompletePackageInterface;
use Composer\Package\RootPackage;
@@ -24,6 +25,8 @@
use Composer\Repository\RepositoryFactory;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
+use Composer\Semver\Constraint\Bound;
+use Composer\Util\Platform;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Composer\Package\Version\VersionParser;
@@ -102,13 +105,30 @@ protected function doExecute(InputInterface $input, OutputInterface $output, boo
// If the version we ask for is not installed then we need to locate it in remote repos and add it.
// This is needed for why-not to resolve conflicts from an uninstalled version against installed packages.
- if (!$installedRepo->findPackage($needle, $textConstraint)) {
+ $matchedPackage = $installedRepo->findPackage($needle, $textConstraint);
+ if (!$matchedPackage) {
$defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO(), $composer->getConfig(), $composer->getRepositoryManager()));
if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
$installedRepo->addRepository(new InstalledArrayRepository([clone $match]));
+ } elseif (PlatformRepository::isPlatformPackage($needle)) {
+ $parser = new VersionParser();
+ $constraint = $parser->parseConstraints($textConstraint);
+ if ($constraint->getLowerBound() !== Bound::zero()) {
+ $tempPlatformPkg = new Package($needle, $constraint->getLowerBound()->getVersion(), $constraint->getLowerBound()->getVersion());
+ $installedRepo->addRepository(new InstalledArrayRepository([$tempPlatformPkg]));
+ }
} else {
$this->getIO()->writeError('Package "'.$needle.'" could not be found with constraint "'.$textConstraint.'", results below will most likely be incomplete.');
}
+ } elseif (PlatformRepository::isPlatformPackage($needle)) {
+ $extraNotice = '';
+ if (($matchedPackage->getExtra()['config.platform'] ?? false) === true) {
+ $extraNotice = ' (version provided by config.platform)';
+ }
+ $this->getIO()->writeError('Package "'.$needle.' '.$textConstraint.'" found in version "'.$matchedPackage->getPrettyVersion().'"'.$extraNotice.'.');
+ } elseif ($inverted) {
+ $this->getIO()->write('Package "'.$needle.'" '.$matchedPackage->getPrettyVersion().' is already installed! To find out why, run `composer why '.$needle.'`');
+ return 0;
}
// Include replaced packages for inverted lookups as they are then the actual starting point to consider
@@ -154,7 +174,7 @@ protected function doExecute(InputInterface $input, OutputInterface $output, boo
$this->printTable($output, $results);
}
- if ($inverted && $input->hasArgument(self::ARGUMENT_CONSTRAINT)) {
+ if ($inverted && $input->hasArgument(self::ARGUMENT_CONSTRAINT) && !PlatformRepository::isPlatformPackage($needle)) {
$composerCommand = 'update';
foreach ($composer->getPackage()->getRequires() as $rootRequirement) {
@@ -180,9 +200,9 @@ protected function doExecute(InputInterface $input, OutputInterface $output, boo
/**
* Assembles and prints a bottom-up table of the dependencies.
*
- * @param array{PackageInterface, Link, mixed}[] $results
+ * @param array{PackageInterface, Link, array|false}[] $results
*/
- protected function printTable(OutputInterface $output, $results): void
+ protected function printTable(OutputInterface $output, array $results): void
{
$table = [];
$doubles = [];
@@ -204,13 +224,13 @@ protected function printTable(OutputInterface $output, $results): void
$packageUrl = PackageInfo::getViewSourceOrHomepageUrl($package);
$nameWithLink = $packageUrl !== null ? '' . $package->getPrettyName() . '>' : $package->getPrettyName();
$rows[] = [$nameWithLink, $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint())];
- if ($children) {
+ if (is_array($children)) {
$queue = array_merge($queue, $children);
}
}
$results = $queue;
$table = array_merge($rows, $table);
- } while (!empty($results));
+ } while (\count($results) > 0);
$this->renderTable($table, $output);
}
@@ -237,7 +257,7 @@ protected function initStyles(OutputInterface $output): void
/**
* Recursively prints a tree of the selected results.
*
- * @param array{PackageInterface, Link, mixed[]|bool}[] $results Results to be printed at this level.
+ * @param array{PackageInterface, Link, array|false}[] $results Results to be printed at this level.
* @param string $prefix Prefix of the current tree level.
* @param int $level Current level of recursion.
*/
@@ -258,7 +278,7 @@ protected function printTree(array $results, string $prefix = '', int $level = 1
$linkText = sprintf('%s <%s>%s%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
$circularWarn = $children === false ? '(circular dependency aborted here)' : '';
$this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
- if ($children) {
+ if (is_array($children)) {
$this->printTree($children, $prefix . ($isLast ? ' ' : '│ '), $level + 1);
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/BumpCommand.php b/app/vendor/composer/composer/src/Composer/Command/BumpCommand.php
index db5b9464a..4570ce2a3 100644
--- a/app/vendor/composer/composer/src/Composer/Command/BumpCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/BumpCommand.php
@@ -12,6 +12,7 @@
namespace Composer\Command;
+use Composer\IO\IOInterface;
use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\Locker;
@@ -72,9 +73,28 @@ protected function configure(): void
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
+ return $this->doBump(
+ $this->getIO(),
+ $input->getOption('dev-only'),
+ $input->getOption('no-dev-only'),
+ $input->getOption('dry-run'),
+ $input->getArgument('packages')
+ );
+ }
+
+ /**
+ * @param string[] $packagesFilter
+ * @throws \Seld\JsonLint\ParsingException
+ */
+ public function doBump(
+ IOInterface $io,
+ bool $devOnly,
+ bool $noDevOnly,
+ bool $dryRun,
+ array $packagesFilter
+ ): int {
/** @readonly */
$composerJsonPath = Factory::getComposerFile();
- $io = $this->getIO();
if (!Filesystem::isReadable($composerJsonPath)) {
$io->writeError(''.$composerJsonPath.' is not readable.');
@@ -112,7 +132,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$repo = $composer->getRepositoryManager()->getLocalRepository();
}
- if ($composer->getPackage()->getType() !== 'project' && !$input->getOption('dev-only')) {
+ if ($composer->getPackage()->getType() !== 'project' && !$devOnly) {
$io->writeError('Warning: Bumping dependency constraints is not recommended for libraries as it will narrow down your dependencies and may cause problems for your users.');
$contents = $composerJson->read();
@@ -125,15 +145,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$bumper = new VersionBumper();
$tasks = [];
- if (!$input->getOption('dev-only')) {
+ if (!$devOnly) {
$tasks['require'] = $composer->getPackage()->getRequires();
}
- if (!$input->getOption('no-dev-only')) {
+ if (!$noDevOnly) {
$tasks['require-dev'] = $composer->getPackage()->getDevRequires();
}
- $packagesFilter = $input->getArgument('packages');
if (count($packagesFilter) > 0) {
+ // support proxied args from the update command that contain constraints together with the package names
+ $packagesFilter = array_map(function ($constraint) {
+ return Preg::replace('{[:= ].+}', '', $constraint);
+ }, $packagesFilter);
$pattern = BasePackage::packageNamesToRegexp(array_unique(array_map('strtolower', $packagesFilter)));
foreach ($tasks as $key => $reqs) {
foreach ($reqs as $pkgName => $link) {
@@ -171,8 +194,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}
}
- $dryRun = $input->getOption('dry-run');
-
if (!$dryRun && !$this->updateFileCleanly($composerJson, $updates)) {
$composerDefinition = $composerJson->read();
foreach ($updates as $key => $packages) {
@@ -199,15 +220,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$io->write('No requirements to update in '.$composerJsonPath.'.');
}
- if (!$dryRun && $composer->getLocker()->isLocked() && $changeCount > 0) {
- $contents = file_get_contents($composerJson->getPath());
- if (false === $contents) {
- throw new \RuntimeException('Unable to read '.$composerJson->getPath().' contents to update the lock file hash.');
- }
- $lock = new JsonFile(Factory::getLockFile($composerJsonPath));
- $lockData = $lock->read();
- $lockData['content-hash'] = Locker::getContentHash($contents);
- $lock->write($lockData);
+ if (!$dryRun && $composer->getLocker()->isLocked() && $composer->getConfig()->get('lock') && $changeCount > 0) {
+ $composer->getLocker()->updateHash($composerJson);
}
if ($dryRun && $changeCount > 0) {
diff --git a/app/vendor/composer/composer/src/Composer/Command/CompletionTrait.php b/app/vendor/composer/composer/src/Composer/Command/CompletionTrait.php
index 89c6b68e5..444d69554 100644
--- a/app/vendor/composer/composer/src/Composer/Command/CompletionTrait.php
+++ b/app/vendor/composer/composer/src/Composer/Command/CompletionTrait.php
@@ -117,6 +117,36 @@ private function suggestInstalledPackage(bool $includeRootPackage = true, bool $
};
}
+ /**
+ * Suggest package names from installed.
+ */
+ private function suggestInstalledPackageTypes(bool $includeRootPackage = true): \Closure
+ {
+ return function (CompletionInput $input) use ($includeRootPackage): array {
+ $composer = $this->requireComposer();
+ $installedRepos = [];
+
+ if ($includeRootPackage) {
+ $installedRepos[] = new RootPackageRepository(clone $composer->getPackage());
+ }
+
+ $locker = $composer->getLocker();
+ if ($locker->isLocked()) {
+ $installedRepos[] = $locker->getLockedRepository(true);
+ } else {
+ $installedRepos[] = $composer->getRepositoryManager()->getLocalRepository();
+ }
+
+ $installedRepo = new InstalledRepository($installedRepos);
+
+ return array_values(array_unique(
+ array_map(static function (PackageInterface $package) {
+ return $package->getType();
+ }, $installedRepo->getPackages())
+ ));
+ };
+ }
+
/**
* Suggest package names available on all configured repositories.
*/
diff --git a/app/vendor/composer/composer/src/Composer/Command/ConfigCommand.php b/app/vendor/composer/composer/src/Composer/Command/ConfigCommand.php
index b625cbf1a..de3bd367e 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ConfigCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ConfigCommand.php
@@ -291,7 +291,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$source = $this->config->getSourceOfValue($settingKey);
if (Preg::isMatch('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
- if (!isset($matches[1]) || $matches[1] === '') {
+ if (!isset($matches[1])) {
$value = $data['repositories'] ?? [];
} else {
if (!isset($data['repositories'][$matches[1]])) {
@@ -469,6 +469,18 @@ static function ($val) {
'prepend-autoloader' => [$booleanValidator, $booleanNormalizer],
'disable-tls' => [$booleanValidator, $booleanNormalizer],
'secure-http' => [$booleanValidator, $booleanNormalizer],
+ 'bump-after-update' => [
+ static function ($val): bool {
+ return in_array($val, ['dev', 'no-dev', 'true', 'false', '1', '0'], true);
+ },
+ static function ($val) {
+ if ('dev' === $val || 'no-dev' === $val) {
+ return $val;
+ }
+
+ return $val !== 'false' && (bool) $val;
+ },
+ ],
'cafile' => [
static function ($val): bool {
return file_exists($val) && Filesystem::isReadable($val);
@@ -664,7 +676,7 @@ static function ($vals) {
}],
'minimum-stability' => [
static function ($val): bool {
- return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
+ return isset(BasePackage::STABILITIES[VersionParser::normalizeStability($val)]);
},
static function ($val): string {
return VersionParser::normalizeStability($val);
@@ -1013,7 +1025,7 @@ private function getAuthConfigFile(InputInterface $input, Config $config): strin
}
/**
- * Suggest setting-keys, while taking given options in acount.
+ * Suggest setting-keys, while taking given options in account.
*/
private function suggestSettingKeys(): \Closure
{
diff --git a/app/vendor/composer/composer/src/Composer/Command/CreateProjectCommand.php b/app/vendor/composer/composer/src/Composer/Command/CreateProjectCommand.php
index b7e873684..368516fdb 100644
--- a/app/vendor/composer/composer/src/Composer/Command/CreateProjectCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/CreateProjectCommand.php
@@ -319,14 +319,6 @@ public function installProject(IOInterface $io, Config $config, InputInterface $
$composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
chdir($oldCwd);
- $vendorComposerDir = $config->get('vendor-dir').'/composer';
- if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
- Silencer::call('rmdir', $vendorComposerDir);
- $vendorDir = $config->get('vendor-dir');
- if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
- Silencer::call('rmdir', $vendorDir);
- }
- }
return 0;
}
@@ -338,10 +330,6 @@ public function installProject(IOInterface $io, Config $config, InputInterface $
*/
protected function installRootPackage(InputInterface $input, IOInterface $io, Config $config, string $packageName, PlatformRequirementFilterInterface $platformRequirementFilter, ?string $directory = null, ?string $packageVersion = null, ?string $stability = 'stable', bool $preferSource = false, bool $preferDist = false, bool $installDevPackages = false, ?array $repositories = null, bool $disablePlugins = false, bool $disableScripts = false, bool $noProgress = false, bool $secureHttp = true): bool
{
- if (!$secureHttp) {
- $config->merge(['config' => ['secure-http' => false]], Config::SOURCE_COMMAND);
- }
-
$parser = new VersionParser();
$requirements = $parser->parseNameVersionPairs([$packageName]);
$name = strtolower($requirements[0]['name']);
@@ -354,12 +342,22 @@ protected function installRootPackage(InputInterface $input, IOInterface $io, Co
$parts = explode("/", $name, 2);
$directory = Platform::getCwd() . DIRECTORY_SEPARATOR . array_pop($parts);
}
+ $directory = rtrim($directory, '/\\');
$process = new ProcessExecutor($io);
$fs = new Filesystem($process);
if (!$fs->isAbsolutePath($directory)) {
$directory = Platform::getCwd() . DIRECTORY_SEPARATOR . $directory;
}
+ if ('' === $directory) {
+ throw new \UnexpectedValueException('Got an empty target directory, something went wrong');
+ }
+
+ // set the base dir to ensure $config->all() below resolves the correct absolute paths to vendor-dir etc
+ $config->setBaseDir($directory);
+ if (!$secureHttp) {
+ $config->merge(['config' => ['secure-http' => false]], Config::SOURCE_COMMAND);
+ }
$io->writeError('Creating a "' . $packageName . '" project at "' . $fs->findShortestPath(Platform::getCwd(), $directory, true) . '"');
@@ -375,7 +373,7 @@ protected function installRootPackage(InputInterface $input, IOInterface $io, Co
if (null === $stability) {
if (null === $packageVersion) {
$stability = 'stable';
- } elseif (Preg::isMatchStrictGroups('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
+ } elseif (Preg::isMatchStrictGroups('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::STABILITIES)).')$}i', $packageVersion, $match)) {
$stability = $match[1];
} else {
$stability = VersionParser::parseStability($packageVersion);
@@ -384,12 +382,14 @@ protected function installRootPackage(InputInterface $input, IOInterface $io, Co
$stability = VersionParser::normalizeStability($stability);
- if (!isset(BasePackage::$stabilities[$stability])) {
- throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
+ if (!isset(BasePackage::STABILITIES[$stability])) {
+ throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::STABILITIES)));
}
$composer = $this->createComposerInstance($input, $io, $config->all(), $disablePlugins, $disableScripts);
$config = $composer->getConfig();
+ // set the base dir here again on the new config instance, as otherwise in case the vendor dir is defined in an env var for example it would still override the value set above by $config->all()
+ $config->setBaseDir($directory);
$rm = $composer->getRepositoryManager();
$repositorySet = new RepositorySet($stability);
@@ -404,6 +404,12 @@ protected function installRootPackage(InputInterface $input, IOInterface $io, Co
) {
continue;
}
+
+ // disable symlinking for the root package by default as that most likely makes no sense
+ if (($repoConfig['type'] ?? null) === 'path' && !isset($repoConfig['options']['symlink'])) {
+ $repoConfig['options']['symlink'] = false;
+ }
+
$repositorySet->addRepository(RepositoryFactory::createRepo($io, $config, $repoConfig, $rm));
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/DiagnoseCommand.php b/app/vendor/composer/composer/src/Composer/Command/DiagnoseCommand.php
index fa5e9aa56..8ed8f9433 100644
--- a/app/vendor/composer/composer/src/Composer/Command/DiagnoseCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/DiagnoseCommand.php
@@ -19,6 +19,8 @@
use Composer\Downloader\TransportException;
use Composer\IO\BufferIO;
use Composer\Json\JsonFile;
+use Composer\Json\JsonValidationException;
+use Composer\Package\Locker;
use Composer\Package\RootPackage;
use Composer\Package\Version\VersionParser;
use Composer\Pcre\Preg;
@@ -89,6 +91,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$io->write('Checking composer.json: ', false);
$this->outputResult($this->checkComposerSchema());
+
+ if ($composer->getLocker()->isLocked()) {
+ $io->write('Checking composer.lock: ', false);
+ $this->outputResult($this->checkComposerLockSchema($composer->getLocker()));
+ }
+
$this->process = $composer->getLoop()->getProcessExecutor() ?? new ProcessExecutor($io);
} else {
$this->process = new ProcessExecutor($io);
@@ -117,6 +125,25 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$io->write('Checking https connectivity to packagist: ', false);
$this->outputResult($this->checkHttp('https', $config));
+ foreach ($config->getRepositories() as $repo) {
+ if (($repo['type'] ?? null) === 'composer' && isset($repo['url'])) {
+ $composerRepo = new ComposerRepository($repo, $this->getIO(), $config, $this->httpDownloader);
+ $reflMethod = new \ReflectionMethod($composerRepo, 'getPackagesJsonUrl');
+ if (PHP_VERSION_ID < 80100) {
+ $reflMethod->setAccessible(true);
+ }
+ $url = $reflMethod->invoke($composerRepo);
+ if (!str_starts_with($url, 'http')) {
+ continue;
+ }
+ if (str_starts_with($url, 'https://repo.packagist.org')) {
+ continue;
+ }
+ $io->write('Checking connectivity to ' . $repo['url'].': ', false);
+ $this->outputResult($this->checkComposerRepo($url, $config));
+ }
+ }
+
$proxyManager = ProxyManager::getInstance();
$protos = $config->get('disable-tls') === true ? ['http'] : ['http', 'https'];
try {
@@ -148,7 +175,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
} elseif (10 > $rate['remaining']) {
$io->write('WARNING');
$io->write(sprintf(
- 'Github has a rate limit on their API. '
+ 'GitHub has a rate limit on their API. '
. 'You currently have %u '
. 'out of %u requests left.' . PHP_EOL
. 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
@@ -248,13 +275,34 @@ private function checkComposerSchema()
return true;
}
+ /**
+ * @return string|true
+ */
+ private function checkComposerLockSchema(Locker $locker)
+ {
+ $json = $locker->getJsonFile();
+
+ try {
+ $json->validateSchema(JsonFile::LOCK_SCHEMA);
+ } catch (JsonValidationException $e) {
+ $output = '';
+ foreach ($e->getErrors() as $error) {
+ $output .= ''.$error.''.PHP_EOL;
+ }
+
+ return trim($output);
+ }
+
+ return true;
+ }
+
private function checkGit(): string
{
if (!function_exists('proc_open')) {
return 'proc_open is not available, git cannot be used';
}
- $this->process->execute('git config color.ui', $output);
+ $this->process->execute(['git', 'config', 'color.ui'], $output);
if (strtolower(trim($output)) === 'always') {
return 'Your git color.ui setting is set to always, this is known to create issues. Use "git config --global color.ui true" to set it correctly.';
}
@@ -310,6 +358,45 @@ private function checkHttp(string $proto, Config $config)
return true;
}
+ /**
+ * @return string|string[]|true
+ */
+ private function checkComposerRepo(string $url, Config $config)
+ {
+ $result = $this->checkConnectivityAndComposerNetworkHttpEnablement();
+ if ($result !== true) {
+ return $result;
+ }
+
+ $result = [];
+ if (str_starts_with($url, 'https://') && $config->get('disable-tls') === true) {
+ $tlsWarning = 'Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.';
+ }
+
+ try {
+ $this->httpDownloader->get($url);
+ } catch (TransportException $e) {
+ $hints = HttpDownloader::getExceptionHints($e);
+ if (null !== $hints && count($hints) > 0) {
+ foreach ($hints as $hint) {
+ $result[] = $hint;
+ }
+ }
+
+ $result[] = '[' . get_class($e) . '] ' . $e->getMessage() . '';
+ }
+
+ if (isset($tlsWarning)) {
+ $result[] = $tlsWarning;
+ }
+
+ if (count($result) > 0) {
+ return $result;
+ }
+
+ return true;
+ }
+
/**
* @return string|\Exception
*/
@@ -508,11 +595,11 @@ private function checkComposerAudit(Config $config)
$io = new BufferIO();
$result = $auditor->audit($io, $repoSet, $packages, Auditor::FORMAT_TABLE, true, [], Auditor::ABANDONED_IGNORE);
} catch (\Throwable $e) {
- return 'Failed performing audit: '.$e->getMessage().'>';
+ return 'Failed performing audit: '.$e->getMessage().'>';
}
if ($result > 0) {
- return 'Audit found some issues:>' . PHP_EOL . $io->getOutput();
+ return 'Audit found some issues:>' . PHP_EOL . $io->getOutput();
}
return true;
@@ -526,9 +613,12 @@ private function getCurlVersion(): string
}
$version = curl_version();
+ $hasZstd = isset($version['features']) && defined('CURL_VERSION_ZSTD') && 0 !== ($version['features'] & CURL_VERSION_ZSTD);
return ''.$version['version'].' '.
- 'libz '.(!empty($version['libz_version']) ? $version['libz_version'] : 'missing').' '.
+ 'libz '.($version['libz_version'] ?? 'missing').' '.
+ 'brotli '.($version['brotli_version'] ?? 'missing').' '.
+ 'zstd '.($hasZstd ? 'supported' : 'missing').' '.
'ssl '.($version['ssl_version'] ?? 'missing').'';
}
@@ -630,7 +720,7 @@ private function checkPlatform()
$errors['ioncube'] = ioncube_loader_version();
}
- if (PHP_VERSION_ID < 70205) {
+ if (\PHP_VERSION_ID < 70205) {
$errors['php'] = PHP_VERSION;
}
@@ -678,6 +768,12 @@ private function checkPlatform()
$warnings['onedrive'] = PHP_VERSION;
}
+ if (extension_loaded('uopz')
+ && !(filter_var(ini_get('uopz.disable'), FILTER_VALIDATE_BOOLEAN)
+ || filter_var(ini_get('uopz.exit'), FILTER_VALIDATE_BOOLEAN))) {
+ $warnings['uopz'] = true;
+ }
+
if (!empty($errors)) {
foreach ($errors as $error => $current) {
switch ($error) {
@@ -791,6 +887,11 @@ private function checkPlatform()
$text .= "Upgrade your PHP ({$current}) to use this location with Composer.".PHP_EOL;
break;
+ case 'uopz':
+ $text = "The uopz extension ignores exit calls and may not work with all Composer commands.".PHP_EOL;
+ $text .= "Disabling it when using Composer is recommended.";
+ break;
+
default:
throw new \InvalidArgumentException(sprintf("DiagnoseCommand: Unknown warning type \"%s\". Please report at https://github.com/composer/composer/issues/new.", $warning));
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/DumpAutoloadCommand.php b/app/vendor/composer/composer/src/Composer/Command/DumpAutoloadCommand.php
index c30fae7a8..cc0d7bf80 100644
--- a/app/vendor/composer/composer/src/Composer/Command/DumpAutoloadCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/DumpAutoloadCommand.php
@@ -12,6 +12,7 @@
namespace Composer\Command;
+use Composer\Package\AliasPackage;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Symfony\Component\Console\Input\InputInterface;
@@ -43,6 +44,7 @@ protected function configure()
new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
new InputOption('strict-psr', null, InputOption::VALUE_NONE, 'Return a failed status code (1) if PSR-4 or PSR-0 mapping errors are present. Requires --optimize to work.'),
+ new InputOption('strict-ambiguous', null, InputOption::VALUE_NONE, 'Return a failed status code (2) if the same class is found in multiple files. Requires --optimize to work.'),
])
->setHelp(
<<getPackage();
$config = $composer->getConfig();
+ $missingDependencies = false;
+ foreach ($localRepo->getCanonicalPackages() as $localPkg) {
+ $installPath = $installationManager->getInstallPath($localPkg);
+ if ($installPath !== null && file_exists($installPath) === false) {
+ $missingDependencies = true;
+ $this->getIO()->write('Not all dependencies are installed. Make sure to run a "composer install" to install missing dependencies');
+
+ break;
+ }
+ }
+
$optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
$apcuPrefix = $input->getOption('apcu-prefix');
@@ -74,6 +87,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
if ($input->getOption('strict-psr') && !$optimize && !$authoritative) {
throw new \InvalidArgumentException('--strict-psr mode only works with optimized autoloader, use --optimize or --classmap-authoritative if you want a strict return value.');
}
+ if ($input->getOption('strict-ambiguous') && !$optimize && !$authoritative) {
+ throw new \InvalidArgumentException('--strict-ambiguous mode only works with optimized autoloader, use --optimize or --classmap-authoritative if you want a strict return value.');
+ }
if ($authoritative) {
$this->getIO()->write('Generating optimized autoload files (authoritative)');
@@ -108,7 +124,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
'composer',
$optimize,
null,
- $composer->getLocker()
+ $composer->getLocker(),
+ $input->getOption('strict-ambiguous')
);
$numberOfClasses = count($classMap);
@@ -120,10 +137,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$this->getIO()->write('Generated autoload files');
}
- if ($input->getOption('strict-psr') && count($classMap->getPsrViolations()) > 0) {
+ if ($missingDependencies || ($input->getOption('strict-psr') && count($classMap->getPsrViolations()) > 0)) {
return 1;
}
+ if ($input->getOption('strict-ambiguous') && count($classMap->getAmbiguousClasses(false)) > 0) {
+ return 2;
+ }
+
return 0;
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/HomeCommand.php b/app/vendor/composer/composer/src/Composer/Command/HomeCommand.php
index 5aec6f4c1..3547faec7 100644
--- a/app/vendor/composer/composer/src/Composer/Command/HomeCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/HomeCommand.php
@@ -122,22 +122,20 @@ private function handlePackage(CompletePackageInterface $package, bool $showHome
*/
private function openBrowser(string $url): void
{
- $url = ProcessExecutor::escape($url);
-
$process = new ProcessExecutor($this->getIO());
if (Platform::isWindows()) {
- $process->execute('start "web" explorer ' . $url, $output);
+ $process->execute(['start', '"web"', 'explorer', $url], $output);
return;
}
- $linux = $process->execute('which xdg-open', $output);
- $osx = $process->execute('which open', $output);
+ $linux = $process->execute(['which', 'xdg-open'], $output);
+ $osx = $process->execute(['which', 'open'], $output);
if (0 === $linux) {
- $process->execute('xdg-open ' . $url, $output);
+ $process->execute(['xdg-open', $url], $output);
} elseif (0 === $osx) {
- $process->execute('open ' . $url, $output);
+ $process->execute(['open', $url], $output);
} else {
$this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/InitCommand.php b/app/vendor/composer/composer/src/Composer/Command/InitCommand.php
index 5f6773daf..9a49d595b 100644
--- a/app/vendor/composer/composer/src/Composer/Command/InitCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/InitCommand.php
@@ -21,11 +21,13 @@
use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryFactory;
+use Composer\Spdx\SpdxLicenses;
use Composer\Util\Filesystem;
use Composer\Util\Silencer;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
+use Composer\Util\ProcessExecutor;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\Process;
@@ -61,7 +63,7 @@ protected function configure()
new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
new InputOption('require', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"', null, $this->suggestAvailablePackageInclPlatform()),
new InputOption('require-dev', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require for development with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"', null, $this->suggestAvailablePackageInclPlatform()),
- new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
+ new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::STABILITIES)).')'),
new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
new InputOption('autoload', 'a', InputOption::VALUE_REQUIRED, 'Add PSR-4 autoload mapping. Maps your package\'s namespace to the provided directory. (Expects a relative path, e.g. src/)'),
@@ -89,7 +91,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$allowlist = ['name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license', 'autoload'];
$options = array_filter(array_intersect_key($input->getOptions(), array_flip($allowlist)), function ($val) { return $val !== null && $val !== []; });
- if (isset($options['name']) && !Preg::isMatch('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $options['name'])) {
+ if (isset($options['name']) && !Preg::isMatch('{^[a-z0-9]([_.-]?[a-z0-9]+)*\/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$}D', $options['name'])) {
throw new \InvalidArgumentException(
'The package name '.$options['name'].' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'
);
@@ -272,23 +274,24 @@ protected function interact(InputInterface $input, OutputInterface $output)
$name = $input->getOption('name');
if (null === $name) {
$name = basename($cwd);
- $name = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
- $name = strtolower($name);
+ $name = $this->sanitizePackageNameComponent($name);
+
+ $vendor = $name;
if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) {
- $name = $_SERVER['COMPOSER_DEFAULT_VENDOR'] . '/' . $name;
+ $vendor = $_SERVER['COMPOSER_DEFAULT_VENDOR'];
} elseif (isset($git['github.user'])) {
- $name = $git['github.user'] . '/' . $name;
+ $vendor = $git['github.user'];
} elseif (!empty($_SERVER['USERNAME'])) {
- $name = $_SERVER['USERNAME'] . '/' . $name;
+ $vendor = $_SERVER['USERNAME'];
} elseif (!empty($_SERVER['USER'])) {
- $name = $_SERVER['USER'] . '/' . $name;
+ $vendor = $_SERVER['USER'];
} elseif (get_current_user()) {
- $name = get_current_user() . '/' . $name;
- } else {
- // package names must be in the format foo/bar
- $name .= '/' . $name;
+ $vendor = get_current_user();
}
- $name = strtolower($name);
+
+ $vendor = $this->sanitizePackageNameComponent($vendor);
+
+ $name = $vendor . '/' . $name;
}
$name = $io->askAndValidate(
@@ -298,7 +301,7 @@ static function ($value) use ($name) {
return $name;
}
- if (!Preg::isMatch('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $value)) {
+ if (!Preg::isMatch('{^[a-z0-9]([_.-]?[a-z0-9]+)*\/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$}D', $value)) {
throw new \InvalidArgumentException(
'The package name '.$value.' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'
);
@@ -364,10 +367,10 @@ static function ($value) use ($minimumStability) {
return $minimumStability;
}
- if (!isset(BasePackage::$stabilities[$value])) {
+ if (!isset(BasePackage::STABILITIES[$value])) {
throw new \InvalidArgumentException(
'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
- implode(', ', array_keys(BasePackage::$stabilities))
+ implode(', ', array_keys(BasePackage::STABILITIES))
);
}
@@ -378,11 +381,14 @@ static function ($value) use ($minimumStability) {
);
$input->setOption('stability', $minimumStability);
- $type = $input->getOption('type') ?: false;
+ $type = $input->getOption('type');
$type = $io->ask(
'Package Type (e.g. library, project, metapackage, composer-plugin) ['.$type.']: ',
$type
);
+ if ($type === '' || $type === false) {
+ $type = null;
+ }
$input->setOption('type', $type);
if (null === $license = $input->getOption('license')) {
@@ -395,6 +401,10 @@ static function ($value) use ($minimumStability) {
'License ['.$license.']: ',
$license
);
+ $spdx = new SpdxLicenses();
+ if (null !== $license && !$spdx->validate($license) && $license !== 'proprietary') {
+ throw new \InvalidArgumentException('Invalid license provided: '.$license.'. Only SPDX license identifiers (https://spdx.org/licenses/) or "proprietary" are accepted.');
+ }
$input->setOption('license', $license);
$io->writeError(['', 'Define your dependencies.', '']);
@@ -465,8 +475,6 @@ static function ($value) use ($autoload) {
private function parseAuthorString(string $author): array
{
if (Preg::isMatch('/^(?P[- .,\p{L}\p{N}\p{Mn}\'’"()]+)(?:\s+<(?P.+?)>)?$/u', $author, $match)) {
- assert(is_string($match['name']));
-
if (null !== $match['email'] && !$this->isValidEmail($match['email'])) {
throw new \InvalidArgumentException('Invalid email "'.$match['email'].'"');
}
@@ -529,15 +537,11 @@ protected function getGitConfig(): array
return $this->gitConfig;
}
- $finder = new ExecutableFinder();
- $gitBin = $finder->find('git');
+ $process = new ProcessExecutor($this->getIO());
- $cmd = new Process([$gitBin, 'config', '-l']);
- $cmd->run();
-
- if ($cmd->isSuccessful()) {
+ if (0 === $process->execute(['git', 'config', '-l'], $output)) {
$this->gitConfig = [];
- Preg::matchAllStrictGroups('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches);
+ Preg::matchAllStrictGroups('{^([^=]+)=(.*)$}m', $output, $matches);
foreach ($matches[1] as $key => $match) {
$this->gitConfig[$match] = $matches[2][$key];
}
@@ -633,4 +637,14 @@ private function hasDependencies(array $options): bool
return !empty($requires) || !empty($devRequires);
}
+
+ private function sanitizePackageNameComponent(string $name): string
+ {
+ $name = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
+ $name = strtolower($name);
+ $name = Preg::replace('{^[_.-]+|[_.-]+$|[^a-z0-9_.-]}u', '', $name);
+ $name = Preg::replace('{([_.-]){2,}}u', '$1', $name);
+
+ return $name;
+ }
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/OutdatedCommand.php b/app/vendor/composer/composer/src/Composer/Command/OutdatedCommand.php
index 139fe45a8..0fea6dc09 100644
--- a/app/vendor/composer/composer/src/Composer/Command/OutdatedCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/OutdatedCommand.php
@@ -71,6 +71,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int
'command' => 'show',
'--latest' => true,
];
+ if ($input->getOption('no-interaction')) {
+ $args['--no-interaction'] = true;
+ }
+ if ($input->getOption('no-plugins')) {
+ $args['--no-plugins'] = true;
+ }
+ if ($input->getOption('no-scripts')) {
+ $args['--no-scripts'] = true;
+ }
+ if ($input->getOption('no-cache')) {
+ $args['--no-cache'] = true;
+ }
if (!$input->getOption('all')) {
$args['--outdated'] = true;
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/PackageDiscoveryTrait.php b/app/vendor/composer/composer/src/Composer/Command/PackageDiscoveryTrait.php
index d95e06de8..0bbd2a48c 100644
--- a/app/vendor/composer/composer/src/Composer/Command/PackageDiscoveryTrait.php
+++ b/app/vendor/composer/composer/src/Composer/Command/PackageDiscoveryTrait.php
@@ -16,6 +16,7 @@
use Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory;
use Composer\IO\IOInterface;
+use Composer\Package\BasePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
@@ -52,6 +53,9 @@ protected function getRepos(): CompositeRepository
return $this->repos;
}
+ /**
+ * @param key-of|null $minimumStability
+ */
private function getRepositorySet(InputInterface $input, ?string $minimumStability = null): RepositorySet
{
$key = $minimumStability ?? 'default';
@@ -64,6 +68,9 @@ private function getRepositorySet(InputInterface $input, ?string $minimumStabili
return $this->repositorySets[$key];
}
+ /**
+ * @return key-of
+ */
private function getMinimumStability(InputInterface $input): string
{
if ($input->hasOption('stability')) { // @phpstan-ignore-line as InitCommand does have this option but not all classes using this trait do
@@ -96,7 +103,7 @@ final protected function determineRequirements(InputInterface $input, OutputInte
foreach ($requires as $requirement) {
if (isset($requirement['version']) && Preg::isMatch('{^\d+(\.\d+)?$}', $requirement['version'])) {
- $io->writeError('The "'.$requirement['version'].'" constraint for "'.$requirement['name'].'" appears too strict and will likely not match what you want. See https://getcomposer.org/constraints');
+ $io->writeError('The "'.$requirement['version'].'" constraint for "'.$requirement['name'].'" appears too strict and will likely not match what you want. See https://getcomposer.org/constraints');
}
if (!isset($requirement['version'])) {
diff --git a/app/vendor/composer/composer/src/Composer/Command/ReinstallCommand.php b/app/vendor/composer/composer/src/Composer/Command/ReinstallCommand.php
index 446d9eec1..cb7882a9c 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ReinstallCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ReinstallCommand.php
@@ -51,7 +51,8 @@ protected function configure(): void
new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'),
new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
- new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'List of package names to reinstall, can include a wildcard (*) to match any substring.', null, $this->suggestInstalledPackage(false)),
+ new InputOption('type', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Filter packages to reinstall by type(s)', null, $this->suggestInstalledPackageTypes(false)),
+ new InputArgument('packages', InputArgument::IS_ARRAY, 'List of package names to reinstall, can include a wildcard (*) to match any substring.', null, $this->suggestInstalledPackage(false)),
])
->setHelp(
<<getRepositoryManager()->getLocalRepository();
$packagesToReinstall = [];
$packageNamesToReinstall = [];
- foreach ($input->getArgument('packages') as $pattern) {
- $patternRegexp = BasePackage::packageNameToRegexp($pattern);
- $matched = false;
+ if (\count($input->getOption('type')) > 0) {
+ if (\count($input->getArgument('packages')) > 0) {
+ throw new \InvalidArgumentException('You cannot specify package names and filter by type at the same time.');
+ }
foreach ($localRepo->getCanonicalPackages() as $package) {
- if (Preg::isMatch($patternRegexp, $package->getName())) {
- $matched = true;
+ if (in_array($package->getType(), $input->getOption('type'), true)) {
$packagesToReinstall[] = $package;
$packageNamesToReinstall[] = $package->getName();
}
}
+ } else {
+ if (\count($input->getArgument('packages')) === 0) {
+ throw new \InvalidArgumentException('You must pass one or more package names to be reinstalled.');
+ }
+ foreach ($input->getArgument('packages') as $pattern) {
+ $patternRegexp = BasePackage::packageNameToRegexp($pattern);
+ $matched = false;
+ foreach ($localRepo->getCanonicalPackages() as $package) {
+ if (Preg::isMatch($patternRegexp, $package->getName())) {
+ $matched = true;
+ $packagesToReinstall[] = $package;
+ $packageNamesToReinstall[] = $package->getName();
+ }
+ }
- if (!$matched) {
- $io->writeError('Pattern "' . $pattern . '" does not match any currently installed packages.');
+ if (!$matched) {
+ $io->writeError('Pattern "' . $pattern . '" does not match any currently installed packages.');
+ }
}
}
- if (!$packagesToReinstall) {
+ if (0 === \count($packagesToReinstall)) {
$io->writeError('Found no packages to reinstall, aborting.');
return 1;
diff --git a/app/vendor/composer/composer/src/Composer/Command/RemoveCommand.php b/app/vendor/composer/composer/src/Composer/Command/RemoveCommand.php
index 9803190a4..a68663567 100644
--- a/app/vendor/composer/composer/src/Composer/Command/RemoveCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/RemoveCommand.php
@@ -55,8 +55,8 @@ protected function configure()
new InputOption('no-audit', null, InputOption::VALUE_NONE, 'Skip the audit step after updating the composer.lock file (can also be set via the COMPOSER_NO_AUDIT=1 env var).'),
new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS),
new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
- new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecated, is now default behavior)'),
- new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
+ new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies (can also be set via the COMPOSER_WITH_DEPENDENCIES=1 env var). (Deprecated, is now default behavior)'),
+ new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements (can also be set via the COMPOSER_WITH_ALL_DEPENDENCIES=1 env var).'),
new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-all-dependencies'),
new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
new InputOption('minimal-changes', 'm', InputOption::VALUE_NONE, 'During an update with -w/-W, only perform absolutely necessary changes to transitive dependencies (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).'),
diff --git a/app/vendor/composer/composer/src/Composer/Command/RequireCommand.php b/app/vendor/composer/composer/src/Composer/Command/RequireCommand.php
index b7ee15681..09eab3e26 100644
--- a/app/vendor/composer/composer/src/Composer/Command/RequireCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/RequireCommand.php
@@ -95,8 +95,8 @@ protected function configure()
new InputOption('no-audit', null, InputOption::VALUE_NONE, 'Skip the audit step after updating the composer.lock file (can also be set via the COMPOSER_NO_AUDIT=1 env var).'),
new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS),
new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
- new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
- new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
+ new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements (can also be set via the COMPOSER_WITH_DEPENDENCIES=1 env var).'),
+ new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements (can also be set via the COMPOSER_WITH_ALL_DEPENDENCIES=1 env var).'),
new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-dependencies'),
new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-all-dependencies'),
new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
@@ -231,7 +231,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$requirements = $this->formatRequirements($requirements);
- if (!$input->getOption('dev') && $io->isInteractive()) {
+ if (!$input->getOption('dev') && $io->isInteractive() && !$composer->isGlobal()) {
$devPackages = [];
$devTags = ['dev', 'testing', 'static analysis'];
$currentRequiresByKey = $this->getPackagesByRequireKey();
@@ -402,6 +402,8 @@ private function getPackagesByRequireKey(): array
/**
* @param array $requirements
+ * @param 'require'|'require-dev' $requireKey
+ * @param 'require'|'require-dev' $removeKey
* @throws \Exception
*/
private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements, string $requireKey, string $removeKey): int
@@ -552,22 +554,15 @@ private function updateRequirementsAfterResolution(array $requirementsToUpdate,
if (!$dryRun) {
$this->updateFile($this->json, $requirements, $requireKey, $removeKey, $sortPackages);
- if ($locker->isLocked()) {
- $contents = file_get_contents($this->json->getPath());
- if (false === $contents) {
- throw new \RuntimeException('Unable to read '.$this->json->getPath().' contents to update the lock file hash.');
- }
- $lockFile = Factory::getLockFile($this->json->getPath());
- if (file_exists($lockFile)) {
- $lockMtime = filemtime($lockFile);
- $lock = new JsonFile($lockFile);
- $lockData = $lock->read();
- $lockData['content-hash'] = Locker::getContentHash($contents);
- $lock->write($lockData);
- if (is_int($lockMtime)) {
- @touch($lockFile, $lockMtime);
+ if ($locker->isLocked() && $composer->getConfig()->get('lock')) {
+ $stabilityFlags = RootPackageLoader::extractStabilityFlags($requirements, $composer->getPackage()->getMinimumStability(), []);
+ $locker->updateHash($this->json, function (array $lockData) use ($stabilityFlags) {
+ foreach ($stabilityFlags as $packageName => $flag) {
+ $lockData['stability-flags'][$packageName] = $flag;
}
- }
+
+ return $lockData;
+ });
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/SelfUpdateCommand.php b/app/vendor/composer/composer/src/Composer/Command/SelfUpdateCommand.php
index 26d9f7546..1bf2e57d4 100644
--- a/app/vendor/composer/composer/src/Composer/Command/SelfUpdateCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/SelfUpdateCommand.php
@@ -23,6 +23,7 @@
use Composer\IO\IOInterface;
use Composer\Downloader\FilesystemException;
use Composer\Downloader\TransportException;
+use Phar;
use Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use Composer\Console\Input\InputArgument;
@@ -116,9 +117,9 @@ class_exists('Composer\Downloader\FilesystemException');
$cacheDir = $config->get('cache-dir');
$rollbackDir = $config->get('data-dir');
$home = $config->get('home');
- $localFilename = realpath($_SERVER['argv'][0]);
- if (false === $localFilename) {
- $localFilename = $_SERVER['argv'][0];
+ $localFilename = Phar::running(false);
+ if ('' === $localFilename) {
+ throw new \RuntimeException('Could not determine the location of the composer.phar file as it appears you are not running this code from a phar archive.');
}
if ($input->getOption('update-keys')) {
@@ -146,7 +147,7 @@ class_exists('Composer\Downloader\FilesystemException');
$homeDirOwnerId = fileowner($home);
if (is_array($composerUser) && $homeDirOwnerId !== false) {
$homeOwner = posix_getpwuid($homeDirOwnerId);
- if (is_array($homeOwner) && isset($composerUser['name'], $homeOwner['name']) && $composerUser['name'] !== $homeOwner['name']) {
+ if (is_array($homeOwner) && $composerUser['name'] !== $homeOwner['name']) {
$io->writeError('You are running Composer as "'.$composerUser['name'].'", while "'.$home.'" is owned by "'.$homeOwner['name'].'"');
}
}
@@ -328,8 +329,8 @@ class_exists('Composer\Downloader\FilesystemException');
$verified = 1 === openssl_verify((string) file_get_contents($tempFilename), $signatureSha384, $pubkeyid, $algo);
// PHP 8 automatically frees the key instance and deprecates the function
- if (PHP_VERSION_ID < 80000) {
- // @phpstan-ignore-next-line
+ if (\PHP_VERSION_ID < 80000) {
+ // @phpstan-ignore function.deprecated
openssl_free_key($pubkeyid);
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/ShowCommand.php b/app/vendor/composer/composer/src/Composer/Command/ShowCommand.php
index a1e7eb059..14c9a4c32 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ShowCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ShowCommand.php
@@ -43,6 +43,7 @@
use Composer\Semver\Semver;
use Composer\Spdx\SpdxLicenses;
use Composer\Util\PackageInfo;
+use DateTimeInterface;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
@@ -493,7 +494,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
$writeLatest = $writeVersion && $showLatest;
$writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
- $writeReleaseDate = $writeLatest && $input->getOption('sort-by-age');
+ $writeReleaseDate = $writeLatest && ($input->getOption('sort-by-age') || $format === 'json');
$hasOutdatedPackages = false;
@@ -550,8 +551,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$packageViewData['release-age'] = 'from '.$packageViewData['release-age'];
}
$releaseDateLength = max($releaseDateLength, strlen($packageViewData['release-age']));
+ $packageViewData['release-date'] = $package->getReleaseDate()->format(DateTimeInterface::ATOM);
} else {
$packageViewData['release-age'] = '';
+ $packageViewData['release-date'] = '';
}
}
if ($writeLatest && $latestPackage) {
@@ -561,6 +564,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}
$packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
$latestLength = max($latestLength, strlen($packageViewData['latest']));
+
+ if ($latestPackage->getReleaseDate() !== null) {
+ $packageViewData['latest-release-date'] = $latestPackage->getReleaseDate()->format(DateTimeInterface::ATOM);
+ } else {
+ $packageViewData['latest-release-date'] = '';
+ }
} elseif ($writeLatest) {
$packageViewData['latest'] = '[none matched]';
$packageViewData['latest-status'] = 'up-to-date';
@@ -808,7 +817,8 @@ protected function getPackage(InstalledRepository $installedRepo, RepositoryInte
$pool = $repositorySet->createPoolForPackage($name);
}
$matches = $pool->whatProvides($name, $constraint);
- foreach ($matches as $index => $package) {
+ $literals = [];
+ foreach ($matches as $package) {
// avoid showing the 9999999-dev alias if the default branch has no branch-alias set
if ($package instanceof AliasPackage && $package->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
$package = $package->getAliasOf();
@@ -820,11 +830,12 @@ protected function getPackage(InstalledRepository $installedRepo, RepositoryInte
}
$versions[$package->getPrettyVersion()] = $package->getVersion();
- $matches[$index] = $package->getId();
+ $literals[] = $package->getId();
}
// select preferred package according to policy rules
- if (null === $matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, $matches)) {
+ if (null === $matchedPackage && \count($literals) > 0) {
+ $preferred = $policy->selectPreferredPackages($pool, $literals);
$matchedPackage = $pool->literalToPackage($preferred[0]);
}
@@ -1454,7 +1465,7 @@ private function findLatestPackage(PackageInterface $package, Composer $composer
$stability = $composer->getPackage()->getMinimumStability();
$flags = $composer->getPackage()->getStabilityFlags();
if (isset($flags[$name])) {
- $stability = array_search($flags[$name], BasePackage::$stabilities, true);
+ $stability = array_search($flags[$name], BasePackage::STABILITIES, true);
}
$bestStability = $stability;
diff --git a/app/vendor/composer/composer/src/Composer/Command/StatusCommand.php b/app/vendor/composer/composer/src/Composer/Command/StatusCommand.php
index 780f70031..5d90b3105 100644
--- a/app/vendor/composer/composer/src/Composer/Command/StatusCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/StatusCommand.php
@@ -92,7 +92,7 @@ private function doExecute(InputInterface $input): int
$vcsVersionChanges = [];
$parser = new VersionParser;
- $guesser = new VersionGuesser($composer->getConfig(), $composer->getLoop()->getProcessExecutor() ?? new ProcessExecutor($io), $parser);
+ $guesser = new VersionGuesser($composer->getConfig(), $composer->getLoop()->getProcessExecutor() ?? new ProcessExecutor($io), $parser, $io);
$dumper = new ArrayDumper;
// list packages
diff --git a/app/vendor/composer/composer/src/Composer/Command/UpdateCommand.php b/app/vendor/composer/composer/src/Composer/Command/UpdateCommand.php
index b4478cd04..21d6c3f19 100644
--- a/app/vendor/composer/composer/src/Composer/Command/UpdateCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/UpdateCommand.php
@@ -16,20 +16,28 @@
use Composer\DependencyResolver\Request;
use Composer\Installer;
use Composer\IO\IOInterface;
+use Composer\Package\BasePackage;
use Composer\Package\Loader\RootPackageLoader;
+use Composer\Package\PackageInterface;
+use Composer\Package\Version\VersionSelector;
use Composer\Pcre\Preg;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Package\Version\VersionParser;
+use Composer\Repository\CompositeRepository;
+use Composer\Repository\PlatformRepository;
+use Composer\Repository\RepositoryInterface;
+use Composer\Repository\RepositorySet;
+use Composer\Semver\Constraint\MultiConstraint;
use Composer\Semver\Intervals;
use Composer\Util\HttpDownloader;
use Composer\Advisory\Auditor;
+use Composer\Util\Platform;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputOption;
use Composer\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Question\Question;
/**
* @author Jordi Boggiano
@@ -64,8 +72,8 @@ protected function configure()
new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'),
new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('with-dependencies', 'w', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, except those which are root requirements.'),
- new InputOption('with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, including those which are root requirements.'),
+ new InputOption('with-dependencies', 'w', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, except those which are root requirements (can also be set via the COMPOSER_WITH_DEPENDENCIES=1 env var).'),
+ new InputOption('with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, including those which are root requirements (can also be set via the COMPOSER_WITH_ALL_DEPENDENCIES=1 env var).'),
new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
@@ -76,8 +84,10 @@ protected function configure()
new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies (can also be set via the COMPOSER_PREFER_STABLE=1 env var).'),
new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies (can also be set via the COMPOSER_PREFER_LOWEST=1 env var).'),
new InputOption('minimal-changes', 'm', InputOption::VALUE_NONE, 'During a partial update with -w/-W, only perform absolutely necessary changes to transitive dependencies (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).'),
+ new InputOption('patch-only', null, InputOption::VALUE_NONE, 'Only allow patch version updates for currently installed dependencies.'),
new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
+ new InputOption('bump-after-update', null, InputOption::VALUE_OPTIONAL, 'Runs bump after performing the update.', false, ['dev', 'no-dev', 'all']),
])
->setHelp(
<<getOption('patch-only')) {
+ if (!$composer->getLocker()->isLocked()) {
+ throw new \InvalidArgumentException('patch-only can only be used with a lock file present');
+ }
+ foreach ($composer->getLocker()->getLockedRepository(true)->getCanonicalPackages() as $package) {
+ if ($package->isDev()) {
+ continue;
+ }
+ if (!Preg::isMatch('{^(\d+\.\d+\.\d+)}', $package->getVersion(), $match)) {
+ continue;
+ }
+ $constraint = $parser->parseConstraints('~'.$match[1]);
+ if (isset($temporaryConstraints[$package->getName()])) {
+ $temporaryConstraints[$package->getName()] = MultiConstraint::create([$temporaryConstraints[$package->getName()], $constraint], true);
+ } else {
+ $temporaryConstraints[$package->getName()] = $constraint;
+ }
+ }
+ }
+
if ($input->getOption('interactive')) {
$packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
}
@@ -248,7 +278,28 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$install->disablePlugins();
}
- return $install->run();
+ $result = $install->run();
+
+ if ($result === 0 && !$input->getOption('lock')) {
+ $bumpAfterUpdate = $input->getOption('bump-after-update');
+ if (false === $bumpAfterUpdate) {
+ $bumpAfterUpdate = $composer->getConfig()->get('bump-after-update');
+ }
+
+ if (false !== $bumpAfterUpdate) {
+ $io->writeError('Bumping dependencies');
+ $bumpCommand = new BumpCommand();
+ $bumpCommand->setComposer($composer);
+ $result = $bumpCommand->doBump(
+ $io,
+ $bumpAfterUpdate === 'dev',
+ $bumpAfterUpdate === 'no-dev',
+ $input->getOption('dry-run'),
+ $input->getArgument('packages')
+ );
+ }
+ }
+ return $result;
}
/**
@@ -261,48 +312,53 @@ private function getPackagesInteractively(IOInterface $io, InputInterface $input
throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
}
+ $platformReqFilter = $this->getPlatformRequirementFilter($input);
+ $stabilityFlags = $composer->getPackage()->getStabilityFlags();
$requires = array_merge(
$composer->getPackage()->getRequires(),
$composer->getPackage()->getDevRequires()
);
- $autocompleterValues = [];
- foreach ($requires as $require) {
- $target = $require->getTarget();
- $autocompleterValues[strtolower($target)] = $target;
- }
-
- $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
- foreach ($installedPackages as $package) {
- $autocompleterValues[$package->getName()] = $package->getPrettyName();
- }
-
- $helper = $this->getHelper('question');
- $question = new Question('Enter package name: ', null);
- $io->writeError('Press enter without value to end submission');
+ $filter = \count($packages) > 0 ? BasePackage::packageNamesToRegexp($packages) : null;
- do {
- $autocompleterValues = array_diff($autocompleterValues, $packages);
- $question->setAutocompleterValues($autocompleterValues);
- $addedPackage = $helper->ask($input, $output, $question);
-
- if (!is_string($addedPackage) || empty($addedPackage)) {
- break;
+ $io->writeError('Loading packages that can be updated...');
+ $autocompleterValues = [];
+ $installedPackages = $composer->getLocker()->isLocked() ? $composer->getLocker()->getLockedRepository(true)->getPackages() : $composer->getRepositoryManager()->getLocalRepository()->getPackages();
+ $versionSelector = $this->createVersionSelector($composer);
+ foreach ($installedPackages as $package) {
+ if ($filter !== null && !Preg::isMatch($filter, $package->getName())) {
+ continue;
}
-
- $addedPackage = strtolower($addedPackage);
- if (!in_array($addedPackage, $packages)) {
- $packages[] = $addedPackage;
+ $currentVersion = $package->getPrettyVersion();
+ $constraint = isset($requires[$package->getName()]) ? $requires[$package->getName()]->getPrettyConstraint() : null;
+ $stability = isset($stabilityFlags[$package->getName()]) ? (string) array_search($stabilityFlags[$package->getName()], BasePackage::STABILITIES, true) : $composer->getPackage()->getMinimumStability();
+ $latestVersion = $versionSelector->findBestCandidate($package->getName(), $constraint, $stability, $platformReqFilter);
+ if ($latestVersion !== false && ($package->getVersion() !== $latestVersion->getVersion() || $latestVersion->isDev())) {
+ $autocompleterValues[$package->getName()] = '' . $currentVersion . ' => ' . $latestVersion->getPrettyVersion() . '';
}
- } while (true);
+ }
+ if (0 === \count($installedPackages)) {
+ foreach ($requires as $req => $constraint) {
+ if (PlatformRepository::isPlatformPackage($req)) {
+ continue;
+ }
+ $autocompleterValues[$req] = '';
+ }
+ }
- $packages = array_filter($packages, function (string $pkg) {
- return $pkg !== '';
- });
- if (!$packages) {
- throw new \InvalidArgumentException('You must enter minimum one package.');
+ if (0 === \count($autocompleterValues)) {
+ throw new \RuntimeException('Could not find any package with new versions available');
}
+ $packages = $io->select(
+ 'Select packages: (Select more than one value separated by comma) ',
+ $autocompleterValues,
+ false,
+ 1,
+ 'No package named "%s" is installed.',
+ true
+ );
+
$table = new Table($output);
$table->setHeaders(['Selected packages']);
foreach ($packages as $package) {
@@ -319,4 +375,14 @@ private function getPackagesInteractively(IOInterface $io, InputInterface $input
throw new \RuntimeException('Installation aborted.');
}
+
+ private function createVersionSelector(Composer $composer): VersionSelector
+ {
+ $repositorySet = new RepositorySet();
+ $repositorySet->addRepository(new CompositeRepository(array_filter($composer->getRepositoryManager()->getRepositories(), function (RepositoryInterface $repository) {
+ return !$repository instanceof PlatformRepository;
+ })));
+
+ return new VersionSelector($repositorySet);
+ }
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/ValidateCommand.php b/app/vendor/composer/composer/src/Composer/Command/ValidateCommand.php
index d9d8c7510..fb71081d4 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ValidateCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ValidateCommand.php
@@ -68,7 +68,7 @@ protected function configure(): void
protected function execute(InputInterface $input, OutputInterface $output): int
{
- $file = $input->getArgument('file') ?: Factory::getComposerFile();
+ $file = $input->getArgument('file') ?? Factory::getComposerFile();
$io = $this->getIO();
if (!file_exists($file)) {
@@ -144,16 +144,16 @@ private function outputResult(IOInterface $io, string $name, array &$errors, arr
{
$doPrintSchemaUrl = false;
- if ($errors) {
+ if (\count($errors) > 0) {
$io->writeError('' . $name . ' is invalid, the following errors/warnings were found:');
- } elseif ($publishErrors) {
+ } elseif (\count($publishErrors) > 0 && $checkPublish) {
$io->writeError('' . $name . ' is valid for simple usage with Composer but has');
$io->writeError('strict errors that make it unable to be published as a package');
$doPrintSchemaUrl = $printSchemaUrl;
- } elseif ($warnings) {
+ } elseif (\count($warnings) > 0) {
$io->writeError('' . $name . ' is valid, but with a few warnings');
$doPrintSchemaUrl = $printSchemaUrl;
- } elseif ($lockErrors) {
+ } elseif (\count($lockErrors) > 0) {
$io->write('' . $name . ' is valid but your composer.lock has some '.($checkLock ? 'errors' : 'warnings').'');
} else {
$io->write('' . $name . ' is valid');
@@ -163,13 +163,13 @@ private function outputResult(IOInterface $io, string $name, array &$errors, arr
$io->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema');
}
- if ($errors) {
+ if (\count($errors) > 0) {
$errors = array_map(static function ($err): string {
return '- ' . $err;
}, $errors);
array_unshift($errors, '# General errors');
}
- if ($warnings) {
+ if (\count($warnings) > 0) {
$warnings = array_map(static function ($err): string {
return '- ' . $err;
}, $warnings);
@@ -180,22 +180,17 @@ private function outputResult(IOInterface $io, string $name, array &$errors, arr
$extraWarnings = [];
// If checking publish errors, display them as errors, otherwise just show them as warnings
- if ($publishErrors) {
+ if (\count($publishErrors) > 0 && $checkPublish) {
$publishErrors = array_map(static function ($err): string {
return '- ' . $err;
}, $publishErrors);
- if ($checkPublish) {
- array_unshift($publishErrors, '# Publish errors');
- $errors = array_merge($errors, $publishErrors);
- } else {
- array_unshift($publishErrors, '# Publish warnings');
- $extraWarnings = array_merge($extraWarnings, $publishErrors);
- }
+ array_unshift($publishErrors, '# Publish errors');
+ $errors = array_merge($errors, $publishErrors);
}
// If checking lock errors, display them as errors, otherwise just show them as warnings
- if ($lockErrors) {
+ if (\count($lockErrors) > 0) {
if ($checkLock) {
array_unshift($lockErrors, '# Lock file errors');
$errors = array_merge($errors, $lockErrors);
diff --git a/app/vendor/composer/composer/src/Composer/Compiler.php b/app/vendor/composer/composer/src/Composer/Compiler.php
index 9a2e27f5b..ed5d3ad04 100644
--- a/app/vendor/composer/composer/src/Composer/Compiler.php
+++ b/app/vendor/composer/composer/src/Composer/Compiler.php
@@ -15,6 +15,7 @@
use Composer\Json\JsonFile;
use Composer\CaBundle\CaBundle;
use Composer\Pcre\Preg;
+use Composer\Util\ProcessExecutor;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Process\Process;
use Seld\PharUtils\Timestamps;
@@ -48,23 +49,22 @@ public function compile(string $pharFile = 'composer.phar'): void
unlink($pharFile);
}
- $process = new Process(['git', 'log', '--pretty=%H', '-n1', 'HEAD'], __DIR__);
- if ($process->run() !== 0) {
+ $process = new ProcessExecutor();
+
+ if (0 !== $process->execute(['git', 'log', '--pretty=%H', '-n1', 'HEAD'], $output, dirname(dirname(__DIR__)))) {
throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.');
}
- $this->version = trim($process->getOutput());
+ $this->version = trim($output);
- $process = new Process(['git', 'log', '-n1', '--pretty=%ci', 'HEAD'], __DIR__);
- if ($process->run() !== 0) {
+ if (0 !== $process->execute(['git', 'log', '-n1', '--pretty=%ci', 'HEAD'], $output, dirname(dirname(__DIR__)))) {
throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.');
}
- $this->versionDate = new \DateTime(trim($process->getOutput()));
+ $this->versionDate = new \DateTime(trim($output));
$this->versionDate->setTimezone(new \DateTimeZone('UTC'));
- $process = new Process(['git', 'describe', '--tags', '--exact-match', 'HEAD'], __DIR__);
- if ($process->run() === 0) {
- $this->version = trim($process->getOutput());
+ if (0 === $process->execute(['git', 'describe', '--tags', '--exact-match', 'HEAD'], $output, dirname(dirname(__DIR__)))) {
+ $this->version = trim($output);
} else {
// get branch-alias defined in composer.json for dev-main (if any)
$localConfig = __DIR__.'/../../composer.json';
@@ -75,6 +75,10 @@ public function compile(string $pharFile = 'composer.phar'): void
}
}
+ if ('' === $this->version) {
+ throw new \UnexpectedValueException('Version detection failed');
+ }
+
$phar = new \Phar($pharFile, 0, 'composer.phar');
$phar->setSignatureAlgorithm(\Phar::SHA512);
@@ -116,10 +120,11 @@ public function compile(string $pharFile = 'composer.phar'): void
$finder = new Finder();
$finder->files()
->ignoreVCS(true)
- ->notPath('/\/(composer\.(json|lock)|[A-Z]+\.md(?:own)?|\.gitignore|appveyor.yml|phpunit\.xml\.dist|phpstan\.neon\.dist|phpstan-config\.neon|phpstan-baseline\.neon)$/')
+ ->notPath('/\/(composer\.(?:json|lock)|[A-Z]+\.md(?:own)?|\.gitignore|appveyor.yml|phpunit\.xml\.dist|phpstan\.neon\.dist|phpstan-config\.neon|phpstan-baseline\.neon|UPGRADE.*\.(?:md|txt))$/')
->notPath('/bin\/(jsonlint|validate-json|simple-phpunit|phpstan|phpstan\.phar)(\.bat)?$/')
->notPath('justinrainbow/json-schema/demo/')
->notPath('justinrainbow/json-schema/dist/')
+ ->notPath('composer/pcre/extension.neon')
->notPath('composer/LICENSE')
->exclude('Tests')
->exclude('tests')
@@ -147,7 +152,7 @@ public function compile(string $pharFile = 'composer.phar'): void
foreach ($finder as $file) {
if (false !== ($index = array_search($file->getRealPath(), $extraFiles, true))) {
unset($extraFiles[$index]);
- } elseif (!Preg::isMatch('{(^LICENSE$|\.php$)}', $file->getFilename())) {
+ } elseif (!Preg::isMatch('{(^LICENSE(?:\.txt)?$|\.php$)}', $file->getFilename())) {
$unexpectedFiles[] = (string) $file;
}
diff --git a/app/vendor/composer/composer/src/Composer/Composer.php b/app/vendor/composer/composer/src/Composer/Composer.php
index 8d87940c3..d9e0ccf1a 100644
--- a/app/vendor/composer/composer/src/Composer/Composer.php
+++ b/app/vendor/composer/composer/src/Composer/Composer.php
@@ -51,9 +51,9 @@ class Composer extends PartialComposer
*
* @see getVersion()
*/
- public const VERSION = '2.7.6';
+ public const VERSION = '2.8.10';
public const BRANCH_ALIAS_VERSION = '';
- public const RELEASE_DATE = '2024-05-04 23:03:15';
+ public const RELEASE_DATE = '2025-07-10 19:08:33';
public const SOURCE_VERSION = '';
/**
diff --git a/app/vendor/composer/composer/src/Composer/Config.php b/app/vendor/composer/composer/src/Composer/Config.php
index 8d2885a3c..f39579e06 100644
--- a/app/vendor/composer/composer/src/Composer/Config.php
+++ b/app/vendor/composer/composer/src/Composer/Config.php
@@ -84,6 +84,8 @@ class Config
'gitlab-token' => [],
'http-basic' => [],
'bearer' => [],
+ 'bump-after-update' => false,
+ 'allow-missing-requirements' => false,
];
/** @var array */
@@ -96,7 +98,7 @@ class Config
/** @var array */
private $config;
- /** @var ?string */
+ /** @var ?non-empty-string */
private $baseDir;
/** @var array */
private $repositories;
@@ -125,7 +127,7 @@ public function __construct(bool $useEnvironment = true, ?string $baseDir = null
$this->config = static::$defaultConfig;
$this->repositories = static::$defaultRepositories;
- $this->useEnvironment = (bool) $useEnvironment;
+ $this->useEnvironment = $useEnvironment;
$this->baseDir = is_string($baseDir) && '' !== $baseDir ? $baseDir : null;
foreach ($this->config as $configKey => $configValue) {
@@ -137,6 +139,18 @@ public function __construct(bool $useEnvironment = true, ?string $baseDir = null
}
}
+ /**
+ * Changing this can break path resolution for relative config paths so do not call this without knowing what you are doing
+ *
+ * The $baseDir should be an absolute path and without trailing slash
+ *
+ * @param non-empty-string|null $baseDir
+ */
+ public function setBaseDir(?string $baseDir): void
+ {
+ $this->baseDir = $baseDir;
+ }
+
public function setConfigSource(ConfigSourceInterface $source): void
{
$this->configSource = $source;
@@ -440,9 +454,9 @@ public function get(string $key, int $flags = 0)
$result = $this->config[$key];
$abandonedEnv = $this->getComposerEnv('COMPOSER_AUDIT_ABANDONED');
if (false !== $abandonedEnv) {
- if (!in_array($abandonedEnv, $validChoices = [Auditor::ABANDONED_IGNORE, Auditor::ABANDONED_REPORT, Auditor::ABANDONED_FAIL], true)) {
+ if (!in_array($abandonedEnv, $validChoices = Auditor::ABANDONEDS, true)) {
throw new \RuntimeException(
- "Invalid value for COMPOSER_AUDIT_ABANDONED: {$abandonedEnv}. Expected ".Auditor::ABANDONED_IGNORE.", ".Auditor::ABANDONED_REPORT." or ".Auditor::ABANDONED_FAIL
+ "Invalid value for COMPOSER_AUDIT_ABANDONED: {$abandonedEnv}. Expected one of ".implode(', ', Auditor::ABANDONEDS)."."
);
}
$result['abandoned'] = $abandonedEnv;
@@ -529,7 +543,6 @@ private function process($value, int $flags)
}
return Preg::replaceCallback('#\{\$(.+)\}#', function ($match) use ($flags) {
- assert(is_string($match[1]));
return $this->get($match[1], $flags);
}, $value);
}
@@ -545,7 +558,7 @@ private function realpath(string $path): string
return $path;
}
- return $this->baseDir ? $this->baseDir . '/' . $path : $path;
+ return $this->baseDir !== null ? $this->baseDir . '/' . $path : $path;
}
/**
@@ -584,8 +597,8 @@ private function disableRepoByName(string $name): void
*/
public function prohibitUrlByConfig(string $url, ?IOInterface $io = null, array $repoOptions = []): void
{
- // Return right away if the URL is malformed or custom (see issue #5173)
- if (false === filter_var($url, FILTER_VALIDATE_URL)) {
+ // Return right away if the URL is malformed or custom (see issue #5173), but only for non-HTTP(S) URLs
+ if (false === filter_var($url, FILTER_VALIDATE_URL) && !Preg::isMatch('{^https?://}', $url)) {
return;
}
diff --git a/app/vendor/composer/composer/src/Composer/Config/JsonConfigSource.php b/app/vendor/composer/composer/src/Composer/Config/JsonConfigSource.php
index db3d36dc4..596d14f52 100644
--- a/app/vendor/composer/composer/src/Composer/Config/JsonConfigSource.php
+++ b/app/vendor/composer/composer/src/Composer/Config/JsonConfigSource.php
@@ -162,7 +162,7 @@ public function addProperty(string $name, $value): void
public function removeProperty(string $name): void
{
$this->manipulateJson('removeProperty', static function (&$config, $key): void {
- if (strpos($key, 'extra.') === 0 || strpos($key, 'scripts.') === 0) {
+ if (strpos($key, 'extra.') === 0 || strpos($key, 'scripts.') === 0 || stripos($key, 'autoload.') === 0 || stripos($key, 'autoload-dev.') === 0) {
$bits = explode('.', $key);
$last = array_pop($bits);
$arr = &$config[reset($bits)];
diff --git a/app/vendor/composer/composer/src/Composer/Console/Application.php b/app/vendor/composer/composer/src/Composer/Console/Application.php
index 7919c29d9..3e46b970a 100644
--- a/app/vendor/composer/composer/src/Composer/Console/Application.php
+++ b/app/vendor/composer/composer/src/Composer/Console/Application.php
@@ -19,9 +19,9 @@
use Composer\Util\Silencer;
use LogicException;
use RuntimeException;
-use Seld\Signal\SignalHandler;
use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\Console\Exception\CommandNotFoundException;
+use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputDefinition;
@@ -43,7 +43,6 @@
use Composer\Exception\NoSslException;
use Composer\XdebugHandler\XdebugHandler;
use Symfony\Component\Process\Exception\ProcessTimedOutException;
-use Composer\Util\Http\ProxyManager;
/**
* The console application that handles the commands
@@ -85,9 +84,6 @@ class Application extends BaseApplication
*/
private $initialWorkingDirectory;
- /** @var SignalHandler */
- private $signalHandler;
-
public function __construct(string $name = 'Composer', string $version = '')
{
if (method_exists($this, 'setCatchErrors')) {
@@ -109,12 +105,6 @@ public function __construct(string $name = 'Composer', string $version = '')
$this->io = new NullIO();
- $this->signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) {
- $this->io->writeError('Received '.$signal.', aborting', true, IOInterface::DEBUG);
-
- $handler->exitWithLastSignal();
- });
-
if (!$shutdownRegistered) {
$shutdownRegistered = true;
@@ -136,7 +126,6 @@ public function __construct(string $name = 'Composer', string $version = '')
public function __destruct()
{
- $this->signalHandler->unregister();
}
public function run(?InputInterface $input = null, ?OutputInterface $output = null): int
@@ -153,7 +142,10 @@ public function doRun(InputInterface $input, OutputInterface $output): int
$this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
$this->disableScriptsByDefault = $input->hasParameterOption('--no-scripts');
- $stdin = defined('STDIN') ? STDIN : fopen('php://stdin', 'r');
+ static $stdin = null;
+ if (null === $stdin) {
+ $stdin = defined('STDIN') ? STDIN : fopen('php://stdin', 'r');
+ }
if (Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING') !== '1' && (Platform::getEnv('COMPOSER_NO_INTERACTION') || $stdin === false || !Platform::isTty($stdin))) {
$input->setInteractive(false);
}
@@ -182,7 +174,7 @@ public function doRun(InputInterface $input, OutputInterface $output): int
// determine command name to be executed without including plugin commands
$commandName = '';
- if ($name = $this->getCommandName($input)) {
+ if ($name = $this->getCommandNameBeforeBinding($input)) {
try {
$commandName = $this->find($name)->getName();
} catch (CommandNotFoundException $e) {
@@ -193,13 +185,29 @@ public function doRun(InputInterface $input, OutputInterface $output): int
}
// prompt user for dir change if no composer.json is present in current dir
- if ($io->isInteractive() && null === $newWorkDir && !in_array($commandName, ['', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project', 'outdated'], true) && !file_exists(Factory::getComposerFile()) && ($useParentDirIfNoJsonAvailable = $this->getUseParentDirConfigValue()) !== false) {
+ if (
+ null === $newWorkDir
+ // do not prompt for commands that can function without composer.json
+ && !in_array($commandName, ['', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project', 'outdated'], true)
+ && !file_exists(Factory::getComposerFile())
+ // if use-parent-dir is disabled we should not prompt
+ && ($useParentDirIfNoJsonAvailable = $this->getUseParentDirConfigValue()) !== false
+ // config --file ... should not prompt
+ && ($commandName !== 'config' || ($input->hasParameterOption('--file', true) === false && $input->hasParameterOption('-f', true) === false))
+ // calling a command's help should not prompt
+ && $input->hasParameterOption('--help', true) === false
+ && $input->hasParameterOption('-h', true) === false
+ ) {
$dir = dirname(Platform::getCwd(true));
$home = realpath(Platform::getEnv('HOME') ?: Platform::getEnv('USERPROFILE') ?: '/');
// abort when we reach the home dir or top of the filesystem
while (dirname($dir) !== $dir && $dir !== $home) {
if (file_exists($dir.'/'.Factory::getComposerFile())) {
+ if ($useParentDirIfNoJsonAvailable !== true && !$io->isInteractive()) {
+ $io->writeError('No composer.json in current directory, to use the one at '.$dir.' run interactively or set config.use-parent-dir to true');
+ break;
+ }
if ($useParentDirIfNoJsonAvailable === true || $io->askConfirmation('No composer.json in current directory, do you want to use the one at '.$dir.'? [Y,n]? ')) {
if ($useParentDirIfNoJsonAvailable === true) {
$io->writeError('No composer.json in current directory, changing working directory to '.$dir.'');
@@ -213,16 +221,13 @@ public function doRun(InputInterface $input, OutputInterface $output): int
}
$dir = dirname($dir);
}
+ unset($dir, $home);
}
$needsSudoCheck = !Platform::isWindows()
&& function_exists('exec')
&& !Platform::getEnv('COMPOSER_ALLOW_SUPERUSER')
- && (ini_get('open_basedir') || (
- !file_exists('/.dockerenv')
- && !file_exists('/run/.containerenv')
- && !file_exists('/var/run/.containerenv')
- ));
+ && !Platform::isDocker();
$isNonAllowedRoot = false;
// Clobber sudo credentials if COMPOSER_ALLOW_SUPERUSER is not set before loading plugins
@@ -275,7 +280,8 @@ public function doRun(InputInterface $input, OutputInterface $output): int
if ($this->has($command->getName())) {
$io->writeError('Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped');
} else {
- $this->add($command);
+ // Compatibility layer for symfony/console <7.4
+ method_exists($this, 'addCommand') ? $this->addCommand($command) : $this->add($command);
}
}
} catch (NoSslException $e) {
@@ -307,7 +313,7 @@ public function doRun(InputInterface $input, OutputInterface $output): int
// determine command name to be executed incl plugin commands, and check if it's a proxy command
$isProxyCommand = false;
- if ($name = $this->getCommandName($input)) {
+ if ($name = $this->getCommandNameBeforeBinding($input)) {
try {
$command = $this->find($name);
$commandName = $command->getName();
@@ -325,7 +331,7 @@ public function doRun(InputInterface $input, OutputInterface $output): int
function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
), true, IOInterface::DEBUG);
- if (PHP_VERSION_ID < 70205) {
+ if (\PHP_VERSION_ID < 70205) {
$io->writeError('Composer supports PHP 7.2.5 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.'. Upgrading is strongly recommended but you can use Composer 2.2.x LTS as a fallback.');
}
@@ -352,7 +358,7 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
// Check system temp folder for usability as it can cause weird runtime issues otherwise
Silencer::call(static function () use ($io): void {
$pid = function_exists('getmypid') ? getmypid() . '-' : '';
- $tempfile = sys_get_temp_dir() . '/temp-' . $pid . md5(microtime());
+ $tempfile = sys_get_temp_dir() . '/temp-' . $pid . bin2hex(random_bytes(5));
if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) === __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
$io->writeError(sprintf('PHP temp directory (%s) does not exist or is not writable to Composer. Set sys_temp_dir in your php.ini', sys_get_temp_dir()));
}
@@ -375,7 +381,9 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
$aliases = $composer['scripts-aliases'][$script] ?? [];
- $this->add(new Command\ScriptAliasCommand($script, $description, $aliases));
+ $scriptAlias = new Command\ScriptAliasCommand($script, $description, $aliases);
+ // Compatibility layer for symfony/console <7.4
+ method_exists($this, 'addCommand') ? $this->addCommand($scriptAlias) : $this->add($scriptAlias);
}
}
}
@@ -384,8 +392,6 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
}
try {
- $proxyManager = ProxyManager::getInstance();
-
if ($input->hasParameterOption('--profile')) {
$startTime = microtime(true);
$this->io->enableDebugging($startTime);
@@ -404,15 +410,7 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
}
if (isset($startTime)) {
- $io->writeError('Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MiB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MiB), time: '.round(microtime(true) - $startTime, 2).'s');
- }
-
- if ($proxyManager->needsTransitionWarning()) {
- $io->writeError('');
- $io->writeError('Composer now requires separate proxy environment variables for HTTP and HTTPS requests.');
- $io->writeError('Please set `https_proxy` in addition to your existing proxy environment variables.');
- $io->writeError('This fallback (and warning) will be removed in Composer 2.8.0.');
- $io->writeError('https://getcomposer.org/doc/faqs/how-to-use-composer-behind-a-proxy.md');
+ $io->writeError('Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MiB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MiB), time: '.round(microtime(true) - $startTime, 2).'s');
}
return $result;
@@ -446,6 +444,7 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
// as http error codes are all beyond the 255 range of permitted exit codes
if ($e instanceof TransportException) {
$reflProp = new \ReflectionProperty($e, 'code');
+ $reflProp->setAccessible(true);
$reflProp->setValue($e, Installer::ERROR_TRANSPORT_EXCEPTION);
}
@@ -501,6 +500,17 @@ private function hintCommonErrors(\Throwable $exception, OutputInterface $output
$io->writeError('Check https://getcomposer.org/doc/faqs/how-to-use-composer-behind-a-proxy.md for details', true, IOInterface::QUIET);
}
+ if (Platform::isWindows() && $exception instanceof TransportException && str_contains($exception->getMessage(), 'unable to get local issuer certificate')) {
+ $avastDetect = glob('C:\Program Files\Avast*');
+ if (is_array($avastDetect) && count($avastDetect) !== 0) {
+ $io->writeError('The following exception indicates a possible issue with the Avast Firewall', true, IOInterface::QUIET);
+ $io->writeError('Check https://getcomposer.org/local-issuer for details', true, IOInterface::QUIET);
+ } else {
+ $io->writeError('The following exception indicates a possible issue with a Firewall/Antivirus', true, IOInterface::QUIET);
+ $io->writeError('Check https://getcomposer.org/local-issuer for details', true, IOInterface::QUIET);
+ }
+ }
+
if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
$io->writeError('The following exception may be caused by a stale entry in your cmd.exe AutoRun', true, IOInterface::QUIET);
$io->writeError('Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details', true, IOInterface::QUIET);
@@ -636,6 +646,24 @@ protected function getDefaultCommands(): array
return $commands;
}
+ /**
+ * This ensures we can find the correct command name even if a global input option is present before it
+ *
+ * e.g. "composer -d foo bar" should detect bar as the command name, and not foo
+ */
+ private function getCommandNameBeforeBinding(InputInterface $input): ?string
+ {
+ $input = clone $input;
+ try {
+ // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument.
+ $input->bind($this->getDefinition());
+ } catch (ExceptionInterface $e) {
+ // Errors must be ignored, full binding/validation happens later when the command is known.
+ }
+
+ return $input->getFirstArgument();
+ }
+
public function getLongVersion(): string
{
$branchAliasString = '';
diff --git a/app/vendor/composer/composer/src/Composer/Console/Input/InputArgument.php b/app/vendor/composer/composer/src/Composer/Console/Input/InputArgument.php
index b6d064fc8..19aff8c33 100644
--- a/app/vendor/composer/composer/src/Composer/Console/Input/InputArgument.php
+++ b/app/vendor/composer/composer/src/Composer/Console/Input/InputArgument.php
@@ -26,7 +26,7 @@
*
* @internal
*
- * TODO drop when PHP 8.1 / symfony 6.1+ can be required
+ * TODO symfony/console:6.1 drop when PHP 8.1 / symfony 6.1+ can be required
*/
class InputArgument extends BaseInputArgument
{
@@ -59,7 +59,7 @@ public function __construct(string $name, ?int $mode = null, string $description
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$values = $this->suggestedValues;
- if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) { // @phpstan-ignore-line
+ if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) { // @phpstan-ignore function.impossibleType
throw new LogicException(sprintf('Closure for option "%s" must return an array. Got "%s".', $this->getName(), get_debug_type($values)));
}
if ([] !== $values) {
diff --git a/app/vendor/composer/composer/src/Composer/Console/Input/InputOption.php b/app/vendor/composer/composer/src/Composer/Console/Input/InputOption.php
index 75bfe90d9..b5ff333cd 100644
--- a/app/vendor/composer/composer/src/Composer/Console/Input/InputOption.php
+++ b/app/vendor/composer/composer/src/Composer/Console/Input/InputOption.php
@@ -26,7 +26,7 @@
*
* @internal
*
- * TODO drop when PHP 8.1 / symfony 6.1+ can be required
+ * TODO symfony/console:6.1 drop when PHP 8.1 / symfony 6.1+ can be required
*/
class InputOption extends BaseInputOption
{
@@ -62,7 +62,7 @@ public function __construct(string $name, $shortcut = null, ?int $mode = null, s
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$values = $this->suggestedValues;
- if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) { // @phpstan-ignore-line
+ if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) { // @phpstan-ignore function.impossibleType
throw new LogicException(sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->getName(), get_debug_type($values)));
}
if ([] !== $values) {
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Decisions.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Decisions.php
index 9a5c9c235..599110750 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Decisions.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Decisions.php
@@ -28,7 +28,7 @@ class Decisions implements \Iterator, \Countable
/** @var array */
protected $decisionMap;
/**
- * @var array
+ * @var array
*/
protected $decisionQueue = [];
@@ -69,12 +69,12 @@ public function conflict(int $literal): bool
public function decided(int $literalOrPackageId): bool
{
- return !empty($this->decisionMap[abs($literalOrPackageId)]);
+ return ($this->decisionMap[abs($literalOrPackageId)] ?? 0) !== 0;
}
public function undecided(int $literalOrPackageId): bool
{
- return empty($this->decisionMap[abs($literalOrPackageId)]);
+ return ($this->decisionMap[abs($literalOrPackageId)] ?? 0) === 0;
}
public function decidedInstall(int $literalOrPackageId): bool
@@ -94,7 +94,7 @@ public function decisionLevel(int $literalOrPackageId): int
return 0;
}
- public function decisionRule(int $literalOrPackageId): ?Rule
+ public function decisionRule(int $literalOrPackageId): Rule
{
$packageId = abs($literalOrPackageId);
@@ -104,7 +104,7 @@ public function decisionRule(int $literalOrPackageId): ?Rule
}
}
- return null;
+ throw new \LogicException('Did not find a decision rule using '.$literalOrPackageId);
}
/**
@@ -219,7 +219,7 @@ public function toString(?Pool $pool = null): string
ksort($decisionMap);
$str = '[';
foreach ($decisionMap as $packageId => $level) {
- $str .= (($pool) ? $pool->literalToPackage($packageId) : $packageId).':'.$level.',';
+ $str .= ($pool !== null ? $pool->literalToPackage($packageId) : $packageId).':'.$level.',';
}
$str .= ']';
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php
index f8176ae72..590187026 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php
@@ -30,7 +30,7 @@ class DefaultPolicy implements PolicyInterface
private $preferLowest;
/** @var array|null */
private $preferredVersions;
- /** @var array>> */
+ /** @var array>> */
private $preferredPackageResultCachePerPool;
/** @var array> */
private $sortingCachePerPool;
@@ -53,11 +53,11 @@ public function __construct(bool $preferStable = false, bool $preferLowest = fal
public function versionCompare(PackageInterface $a, PackageInterface $b, string $operator): bool
{
if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
- return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
+ return BasePackage::STABILITIES[$stabA] < BasePackage::STABILITIES[$stabB];
}
// dev versions need to be compared as branches via matchSpecific's special treatment, the rest can be optimized with compiling matcher
- if (strpos($a->getVersion(), 'dev-') === 0 || strpos($b->getVersion(), 'dev-') === 0) {
+ if (($a->isDev() && str_starts_with($a->getVersion(), 'dev-')) || ($b->isDev() && str_starts_with($b->getVersion(), 'dev-'))) {
$constraint = new Constraint($operator, $b->getVersion());
$version = new Constraint('==', $a->getVersion());
@@ -68,9 +68,8 @@ public function versionCompare(PackageInterface $a, PackageInterface $b, string
}
/**
- * @param int[] $literals
- * @param string $requiredPackage
- * @return int[]
+ * @param non-empty-list $literals
+ * @return non-empty-list
*/
public function selectPreferredPackages(Pool $pool, array $literals, ?string $requiredPackage = null): array
{
@@ -118,8 +117,8 @@ public function selectPreferredPackages(Pool $pool, array $literals, ?string $re
}
/**
- * @param int[] $literals
- * @return array
+ * @param non-empty-list $literals
+ * @return non-empty-array>
*/
protected function groupLiteralsByName(Pool $pool, array $literals): array
{
@@ -164,7 +163,7 @@ public function compareByPriority(Pool $pool, BasePackage $a, BasePackage $b, ?s
// for replacers not replacing each other, put a higher prio on replacing
// packages with the same vendor as the required package
- if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
+ if ($requiredPackage !== null && false !== ($pos = strpos($requiredPackage, '/'))) {
$requiredVendor = substr($requiredPackage, 0, $pos);
$aIsSameVendor = strpos($a->getName(), $requiredVendor) === 0;
@@ -205,8 +204,8 @@ protected function replaces(BasePackage $source, BasePackage $target): bool
}
/**
- * @param int[] $literals
- * @return int[]
+ * @param list $literals
+ * @return list
*/
protected function pruneToBestVersion(Pool $pool, array $literals): array
{
@@ -252,8 +251,8 @@ protected function pruneToBestVersion(Pool $pool, array $literals): array
*
* If no package is a local alias, nothing happens
*
- * @param int[] $literals
- * @return int[]
+ * @param list $literals
+ * @return list
*/
protected function pruneRemoteAliases(Pool $pool, array $literals): array
{
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/GenericRule.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/GenericRule.php
index f7cf7f23c..64dd7a215 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/GenericRule.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/GenericRule.php
@@ -46,7 +46,10 @@ public function getLiterals(): array
*/
public function getHash()
{
- $data = unpack('ihash', md5(implode(',', $this->literals), true));
+ $data = unpack('ihash', (string) hash(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', implode(',', $this->literals), true));
+ if (false === $data) {
+ throw new \RuntimeException('Failed unpacking: '.implode(', ', $this->literals));
+ }
return $data['hash'];
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php
index 4826489d2..a61094755 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php
@@ -19,11 +19,11 @@
*/
class MultiConflictRule extends Rule
{
- /** @var list */
+ /** @var non-empty-list */
protected $literals;
/**
- * @param list $literals
+ * @param non-empty-list $literals
*/
public function __construct(array $literals, $reason, $reasonData)
{
@@ -40,7 +40,7 @@ public function __construct(array $literals, $reason, $reasonData)
}
/**
- * @return list
+ * @return non-empty-list
*/
public function getLiterals(): array
{
@@ -52,7 +52,10 @@ public function getLiterals(): array
*/
public function getHash()
{
- $data = unpack('ihash', md5('c:'.implode(',', $this->literals), true));
+ $data = unpack('ihash', (string) hash(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', 'c:'.implode(',', $this->literals), true));
+ if (false === $data) {
+ throw new \RuntimeException('Failed unpacking: '.implode(', ', $this->literals));
+ }
return $data['hash'];
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php
index 928e7e0a9..b4511d091 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php
@@ -26,8 +26,8 @@ interface PolicyInterface
public function versionCompare(PackageInterface $a, PackageInterface $b, string $operator): bool;
/**
- * @param int[] $literals
- * @return int[]
+ * @param non-empty-list $literals
+ * @return non-empty-list
*/
public function selectPreferredPackages(Pool $pool, array $literals, ?string $requiredPackage = null): array;
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php
index 52aefa251..68689ed20 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php
@@ -40,7 +40,7 @@ class PoolBuilder
{
/**
* @var int[]
- * @phpstan-var array
+ * @phpstan-var array, BasePackage::STABILITY_*>
*/
private $acceptableStabilities;
/**
@@ -95,7 +95,7 @@ class PoolBuilder
*/
private $loadedPerRepo = [];
/**
- * @var BasePackage[]
+ * @var array
*/
private $packages = [];
/**
@@ -153,7 +153,7 @@ class PoolBuilder
/**
* @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value
- * @phpstan-param array $acceptableStabilities
+ * @phpstan-param array, BasePackage::STABILITY_*> $acceptableStabilities
* @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
* @phpstan-param array $stabilityFlags
* @param array[] $rootAliases
@@ -201,10 +201,14 @@ public function buildPool(array $repositories, Request $request): Pool
{
$this->restrictedPackagesList = $request->getRestrictedPackages() !== null ? array_flip($request->getRestrictedPackages()) : null;
- if ($request->getUpdateAllowList()) {
+ if (\count($request->getUpdateAllowList()) > 0) {
$this->updateAllowList = $request->getUpdateAllowList();
$this->warnAboutNonMatchingUpdateAllowList($request);
+ if (null === $request->getLockedRepository()) {
+ throw new \LogicException('No lock repo present and yet a partial update was requested.');
+ }
+
foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) {
if (!$this->isUpdateAllowed($lockedPackage)) {
// remember which packages we skipped loading remote content for in this partial update
@@ -271,39 +275,45 @@ public function buildPool(array $repositories, Request $request): Pool
}
}
- while (!empty($this->packagesToLoad)) {
+ while (\count($this->packagesToLoad) > 0) {
$this->loadPackagesMarkedForLoading($request, $repositories);
}
if (\count($this->temporaryConstraints) > 0) {
foreach ($this->packages as $i => $package) {
// we check all alias related packages at once, so no need to check individual aliases
- if (!isset($this->temporaryConstraints[$package->getName()]) || $package instanceof AliasPackage) {
+ if ($package instanceof AliasPackage) {
continue;
}
- $constraint = $this->temporaryConstraints[$package->getName()];
- $packageAndAliases = [$i => $package];
- if (isset($this->aliasMap[spl_object_hash($package)])) {
- $packageAndAliases += $this->aliasMap[spl_object_hash($package)];
- }
+ foreach ($package->getNames() as $packageName) {
+ if (!isset($this->temporaryConstraints[$packageName])) {
+ continue;
+ }
- $found = false;
- foreach ($packageAndAliases as $packageOrAlias) {
- if (CompilingMatcher::match($constraint, Constraint::OP_EQ, $packageOrAlias->getVersion())) {
- $found = true;
+ $constraint = $this->temporaryConstraints[$packageName];
+ $packageAndAliases = [$i => $package];
+ if (isset($this->aliasMap[spl_object_hash($package)])) {
+ $packageAndAliases += $this->aliasMap[spl_object_hash($package)];
}
- }
- if (!$found) {
- foreach ($packageAndAliases as $index => $packageOrAlias) {
- unset($this->packages[$index]);
+ $found = false;
+ foreach ($packageAndAliases as $packageOrAlias) {
+ if (CompilingMatcher::match($constraint, Constraint::OP_EQ, $packageOrAlias->getVersion())) {
+ $found = true;
+ }
+ }
+
+ if (!$found) {
+ foreach ($packageAndAliases as $index => $packageOrAlias) {
+ unset($this->packages[$index]);
+ }
}
}
}
}
- if ($this->eventDispatcher) {
+ if ($this->eventDispatcher !== null) {
$prePoolCreateEvent = new PrePoolCreateEvent(
PluginEvents::PRE_POOL_CREATE,
$repositories,
@@ -413,7 +423,7 @@ private function loadPackagesMarkedForLoading(Request $request, array $repositor
$this->packagesToLoad = [];
foreach ($repositories as $repoIndex => $repository) {
- if (empty($packageBatch)) {
+ if (0 === \count($packageBatch)) {
break;
}
@@ -499,7 +509,7 @@ private function loadPackage(Request $request, array $repositories, BasePackage
if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) {
$skippedRootRequires = $this->getSkippedRootRequires($request, $require);
- if ($request->getUpdateAllowTransitiveRootDependencies() || !$skippedRootRequires) {
+ if ($request->getUpdateAllowTransitiveRootDependencies() || 0 === \count($skippedRootRequires)) {
$this->unlockPackage($request, $repositories, $require);
$this->markPackageNameForLoading($request, $require, $linkConstraint);
} else {
@@ -528,7 +538,7 @@ private function loadPackage(Request $request, array $repositories, BasePackage
if (isset($this->loadedPackages[$replace], $this->skippedLoad[$replace])) {
$skippedRootRequires = $this->getSkippedRootRequires($request, $replace);
- if ($request->getUpdateAllowTransitiveRootDependencies() || !$skippedRootRequires) {
+ if ($request->getUpdateAllowTransitiveRootDependencies() || 0 === \count($skippedRootRequires)) {
$this->unlockPackage($request, $repositories, $replace);
// the replaced package only needs to be loaded if something else requires it
$this->markPackageNameForLoadingIfRequired($request, $replace);
@@ -615,7 +625,13 @@ private function isUpdateAllowed(BasePackage $package): bool
private function warnAboutNonMatchingUpdateAllowList(Request $request): void
{
+ if (null === $request->getLockedRepository()) {
+ throw new \LogicException('No lock repo present and yet a partial update was requested.');
+ }
+
foreach ($this->updateAllowList as $pattern) {
+ $matchedPlatformPackage = false;
+
$patternRegexp = BasePackage::packageNameToRegexp($pattern);
// update pattern matches a locked package? => all good
foreach ($request->getLockedRepository()->getPackages() as $package) {
@@ -626,10 +642,16 @@ private function warnAboutNonMatchingUpdateAllowList(Request $request): void
// update pattern matches a root require? => all good, probably a new package
foreach ($request->getRequires() as $packageName => $constraint) {
if (Preg::isMatch($patternRegexp, $packageName)) {
+ if (PlatformRepository::isPlatformPackage($packageName)) {
+ $matchedPlatformPackage = true;
+ continue;
+ }
continue 2;
}
}
- if (strpos($pattern, '*') !== false) {
+ if ($matchedPlatformPackage) {
+ $this->io->writeError('Pattern "' . $pattern . '" listed for update matches platform packages, but these cannot be updated by Composer.');
+ } elseif (strpos($pattern, '*') !== false) {
$this->io->writeError('Pattern "' . $pattern . '" listed for update does not match any locked packages.');
} else {
$this->io->writeError('Package "' . $pattern . '" listed for update is not locked.');
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.php
index c53891fb6..3de9e037b 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.php
@@ -207,7 +207,7 @@ private function optimizeByIdenticalDependencies(Request $request, Pool $pool):
$groupHashParts[] = 'require:' . (string) $requireConstraint;
}
- if ($package->getReplaces()) {
+ if (\count($package->getReplaces()) > 0) {
foreach ($package->getReplaces() as $link) {
if (CompilingMatcher::match($link->getConstraint(), Constraint::OP_EQ, $package->getVersion())) {
// Use the same hash part as the regular require hash because that's what the replacement does
@@ -224,7 +224,7 @@ private function optimizeByIdenticalDependencies(Request $request, Pool $pool):
}
}
- if (!$groupHashParts) {
+ if (0 === \count($groupHashParts)) {
continue;
}
@@ -371,7 +371,7 @@ private function keepPackage(BasePackage $package, array $identicalDefinitionsPe
*/
private function optimizeImpossiblePackagesAway(Request $request, Pool $pool): void
{
- if (count($request->getLockedPackages()) === 0) {
+ if (\count($request->getLockedPackages()) === 0) {
return;
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Problem.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Problem.php
index cf2cb381e..b107dcbb9 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Problem.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Problem.php
@@ -25,6 +25,7 @@
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Package\Version\VersionParser;
use Composer\Repository\PlatformRepository;
+use Composer\Semver\Constraint\MultiConstraint;
/**
* Represents a problem detected while solving dependencies
@@ -79,7 +80,7 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
// TODO doesn't this entirely defeat the purpose of the problem sections? what's the point of sections?
$reasons = array_merge(...array_reverse($this->reasons));
- if (count($reasons) === 1) {
+ if (\count($reasons) === 1) {
reset($reasons);
$rule = current($reasons);
@@ -92,14 +93,67 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
$constraint = $reasonData['constraint'];
$packages = $pool->whatProvides($packageName, $constraint);
- if (count($packages) === 0) {
+ if (\count($packages) === 0) {
return "\n ".implode(self::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $packageName, $constraint));
}
}
+ usort($reasons, function (Rule $rule1, Rule $rule2) use ($pool) {
+ $rule1Prio = $this->getRulePriority($rule1);
+ $rule2Prio = $this->getRulePriority($rule2);
+ if ($rule1Prio !== $rule2Prio) {
+ return $rule2Prio - $rule1Prio;
+ }
+
+ return $this->getSortableString($pool, $rule1) <=> $this->getSortableString($pool, $rule2);
+ });
+
return self::formatDeduplicatedRules($reasons, ' ', $repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool);
}
+ private function getSortableString(Pool $pool, Rule $rule): string
+ {
+ switch ($rule->getReason()) {
+ case Rule::RULE_ROOT_REQUIRE:
+ return $rule->getReasonData()['packageName'];
+ case Rule::RULE_FIXED:
+ return (string) $rule->getReasonData()['package'];
+ case Rule::RULE_PACKAGE_CONFLICT:
+ case Rule::RULE_PACKAGE_REQUIRES:
+ return $rule->getSourcePackage($pool) . '//' . $rule->getReasonData()->getPrettyString($rule->getSourcePackage($pool));
+ case Rule::RULE_PACKAGE_SAME_NAME:
+ case Rule::RULE_PACKAGE_ALIAS:
+ case Rule::RULE_PACKAGE_INVERSE_ALIAS:
+ return (string) $rule->getReasonData();
+ case Rule::RULE_LEARNED:
+ return implode('-', $rule->getLiterals());
+ }
+
+ // @phpstan-ignore deadCode.unreachable
+ throw new \LogicException('Unknown rule type: '.$rule->getReason());
+ }
+
+ private function getRulePriority(Rule $rule): int
+ {
+ switch ($rule->getReason()) {
+ case Rule::RULE_FIXED:
+ return 3;
+ case Rule::RULE_ROOT_REQUIRE:
+ return 2;
+ case Rule::RULE_PACKAGE_CONFLICT:
+ case Rule::RULE_PACKAGE_REQUIRES:
+ return 1;
+ case Rule::RULE_PACKAGE_SAME_NAME:
+ case Rule::RULE_LEARNED:
+ case Rule::RULE_PACKAGE_ALIAS:
+ case Rule::RULE_PACKAGE_INVERSE_ALIAS:
+ return 0;
+ }
+
+ // @phpstan-ignore deadCode.unreachable
+ throw new \LogicException('Unknown rule type: '.$rule->getReason());
+ }
+
/**
* @param Rule[] $rules
* @param array $installedMap A map of all present packages
@@ -136,7 +190,7 @@ public static function formatDeduplicatedRules(array $rules, string $indent, Rep
if (!$isVerbose) {
$versions = self::condenseVersionList($versions, 1);
}
- if (count($versions) > 1) {
+ if (\count($versions) > 1) {
// remove the s from requires/conflicts to correct grammar
$message = Preg::replace('{^(%s%s (?:require|conflict))s}', '$1', $message);
$result[] = sprintf($message, $package, '['.implode(', ', $versions).']');
@@ -224,16 +278,22 @@ public static function getMissingPackageReason(RepositorySet $repositorySet, Req
$ext = substr($packageName, 4);
$msg = "- Root composer.json requires PHP extension ".$packageName.self::constraintToText($constraint).' but ';
- $version = self::getPlatformPackageVersion($pool, $packageName, phpversion($ext) ?: '0');
+ $version = self::getPlatformPackageVersion($pool, $packageName, phpversion($ext) === false ? '0' : phpversion($ext));
if (null === $version) {
+ $providersStr = self::getProvidersList($repositorySet, $packageName, 5);
+ if ($providersStr !== null) {
+ $providersStr = "\n\n Alternatively you can require one of these packages that provide the extension (or parts of it):\n".
+ " Keep in mind that the suggestions are automated and may not be valid or safe to use\n$providersStr";
+ }
+
if (extension_loaded($ext)) {
return [
$msg,
- 'the '.$packageName.' package is disabled by your platform config. Enable it again with "composer config platform.'.$packageName.' --unset".',
+ 'the '.$packageName.' package is disabled by your platform config. Enable it again with "composer config platform.'.$packageName.' --unset".' . $providersStr,
];
}
- return [$msg, 'it is missing from your system. Install or enable PHP\'s '.$ext.' extension.'];
+ return [$msg, 'it is missing from your system. Install or enable PHP\'s '.$ext.' extension.' . $providersStr];
}
return [$msg, 'it has the wrong version installed ('.$version.').'];
@@ -247,7 +307,13 @@ public static function getMissingPackageReason(RepositorySet $repositorySet, Req
return ["- Root composer.json requires linked library ".$packageName.self::constraintToText($constraint).' but ', $error];
}
- return ["- Root composer.json requires linked library ".$packageName.self::constraintToText($constraint).' but ', 'it has the wrong version installed or is missing from your system, make sure to load the extension providing it.'];
+ $providersStr = self::getProvidersList($repositorySet, $packageName, 5);
+ if ($providersStr !== null) {
+ $providersStr = "\n\n Alternatively you can require one of these packages that provide the library (or parts of it):\n".
+ " Keep in mind that the suggestions are automated and may not be valid or safe to use\n$providersStr";
+ }
+
+ return ["- Root composer.json requires linked library ".$packageName.self::constraintToText($constraint).' but ', 'it has the wrong version installed or is missing from your system, make sure to load the extension providing it.'.$providersStr];
}
}
@@ -262,9 +328,21 @@ public static function getMissingPackageReason(RepositorySet $repositorySet, Req
}
}
+ if ($constraint instanceof Constraint && $constraint->getOperator() === Constraint::STR_OP_EQ && Preg::isMatch('{^dev-.*#.*}', $constraint->getPrettyString())) {
+ $newConstraint = Preg::replace('{ +as +([^,\s|]+)$}', '', $constraint->getPrettyString());
+ $packages = $repositorySet->findPackages($packageName, new MultiConstraint([
+ new Constraint(Constraint::STR_OP_EQ, $newConstraint),
+ new Constraint(Constraint::STR_OP_EQ, str_replace('#', '+', $newConstraint))
+ ], false));
+ if (\count($packages) > 0) {
+ return ["- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose, $pool, $constraint).'. The # character in branch names is replaced by a + character. Make sure to require it as "'.str_replace('#', '+', $constraint->getPrettyString()).'".'];
+ }
+ }
+
// first check if the actual requested package is found in normal conditions
// if so it must mean it is rejected by another constraint than the one given here
- if ($packages = $repositorySet->findPackages($packageName, $constraint)) {
+ $packages = $repositorySet->findPackages($packageName, $constraint);
+ if (\count($packages) > 0) {
$rootReqs = $repositorySet->getRootRequires();
if (isset($rootReqs[$packageName])) {
$filtered = array_filter($packages, static function ($p) use ($rootReqs, $packageName): bool {
@@ -276,16 +354,18 @@ public static function getMissingPackageReason(RepositorySet $repositorySet, Req
}
$tempReqs = $repositorySet->getTemporaryConstraints();
- if (isset($tempReqs[$packageName])) {
- $filtered = array_filter($packages, static function ($p) use ($tempReqs, $packageName): bool {
- return $tempReqs[$packageName]->matches(new Constraint('==', $p->getVersion()));
- });
- if (0 === count($filtered)) {
- return ["- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose, $pool, $constraint).' but '.(self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts').' with your temporary update constraint ('.$packageName.':'.$tempReqs[$packageName]->getPrettyString().').'];
+ foreach (reset($packages)->getNames() as $name) {
+ if (isset($tempReqs[$name])) {
+ $filtered = array_filter($packages, static function ($p) use ($tempReqs, $name): bool {
+ return $tempReqs[$name]->matches(new Constraint('==', $p->getVersion()));
+ });
+ if (0 === count($filtered)) {
+ return ["- Root composer.json requires $name".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose, $pool, $constraint).' but '.(self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts').' with your temporary update constraint ('.$name.':'.$tempReqs[$name]->getPrettyString().').'];
+ }
}
}
- if ($lockedPackage) {
+ if ($lockedPackage !== null) {
$fixedConstraint = new Constraint('==', $lockedPackage->getVersion());
$filtered = array_filter($packages, static function ($p) use ($fixedConstraint): bool {
return $fixedConstraint->matches(new Constraint('==', $p->getVersion()));
@@ -299,7 +379,7 @@ public static function getMissingPackageReason(RepositorySet $repositorySet, Req
return !$p->getRepository() instanceof LockArrayRepository;
});
- if (!$nonLockedPackages) {
+ if (0 === \count($nonLockedPackages)) {
return ["- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose, $pool, $constraint).' in the lock file but not in remote repositories, make sure you avoid updating this package to keep the one from the lock file.'];
}
@@ -307,9 +387,11 @@ public static function getMissingPackageReason(RepositorySet $repositorySet, Req
}
// check if the package is found when bypassing stability checks
- if ($packages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES)) {
+ $packages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES);
+ if (\count($packages) > 0) {
// we must first verify if a valid package would be found in a lower priority repository
- if ($allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES)) {
+ $allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES);
+ if (\count($allReposPackages) > 0) {
return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'minimum-stability', $constraint);
}
@@ -317,9 +399,11 @@ public static function getMissingPackageReason(RepositorySet $repositorySet, Req
}
// check if the package is found when bypassing the constraint and stability checks
- if ($packages = $repositorySet->findPackages($packageName, null, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES)) {
+ $packages = $repositorySet->findPackages($packageName, null, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES);
+ if (\count($packages) > 0) {
// we must first verify if a valid package would be found in a lower priority repository
- if ($allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES)) {
+ $allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES);
+ if (\count($allReposPackages) > 0) {
return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'constraint', $constraint);
}
@@ -349,17 +433,8 @@ public static function getMissingPackageReason(RepositorySet $repositorySet, Req
return ["- Root composer.json requires $packageName, it ", 'could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.'];
}
- if ($providers = $repositorySet->getProviders($packageName)) {
- $maxProviders = 20;
- $providersStr = implode(array_map(static function ($p): string {
- $description = $p['description'] ? ' '.substr($p['description'], 0, 100) : '';
-
- return ' - '.$p['name'].$description."\n";
- }, count($providers) > $maxProviders + 1 ? array_slice($providers, 0, $maxProviders) : $providers));
- if (count($providers) > $maxProviders + 1) {
- $providersStr .= ' ... and '.(count($providers) - $maxProviders).' more.'."\n";
- }
-
+ $providersStr = self::getProvidersList($repositorySet, $packageName, 15);
+ if ($providersStr !== null) {
return ["- Root composer.json requires $packageName".self::constraintToText($constraint).", it ", "could not be found in any version, but the following packages provide it:\n".$providersStr." Consider requiring one of these to satisfy the $packageName requirement."];
}
@@ -377,12 +452,12 @@ public static function getPackageList(array $packages, bool $isVerbose, ?Pool $p
foreach ($packages as $package) {
$prepared[$package->getName()]['name'] = $package->getPrettyName();
$prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion().($package instanceof AliasPackage ? ' (alias of '.$package->getAliasOf()->getPrettyVersion().')' : '');
- if ($pool && $constraint) {
+ if ($pool !== null && $constraint !== null) {
foreach ($pool->getRemovedVersions($package->getName(), $constraint) as $version => $prettyVersion) {
$prepared[$package->getName()]['versions'][$version] = $prettyVersion;
}
}
- if ($pool && $useRemovedVersionGroup) {
+ if ($pool !== null && $useRemovedVersionGroup) {
foreach ($pool->getRemovedVersionsByPackage(spl_object_hash($package)) as $version => $prettyVersion) {
$prepared[$package->getName()]['versions'][$version] = $prettyVersion;
}
@@ -418,7 +493,7 @@ private static function getPlatformPackageVersion(Pool $pool, string $packageNam
{
$available = $pool->whatProvides($packageName);
- if (count($available)) {
+ if (\count($available) > 0) {
$selected = null;
foreach ($available as $pkg) {
if ($pkg->getRepository() instanceof PlatformRepository) {
@@ -443,7 +518,7 @@ private static function getPlatformPackageVersion(Pool $pool, string $packageNam
$version = $selected->getPrettyVersion();
$extra = $selected->getExtra();
if ($selected instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
- $version .= '; ' . str_replace('Package ', '', $selected->getDescription());
+ $version .= '; ' . str_replace('Package ', '', (string) $selected->getDescription());
}
} else {
return null;
@@ -504,8 +579,8 @@ private static function hasMultipleNames(array $packages): bool
}
/**
- * @param PackageInterface[] $higherRepoPackages
- * @param PackageInterface[] $allReposPackages
+ * @param non-empty-array $higherRepoPackages
+ * @param non-empty-array $allReposPackages
* @return array{0: string, 1: string}
*/
private static function computeCheckForLowerPrioRepo(Pool $pool, bool $isVerbose, string $packageName, array $higherRepoPackages, array $allReposPackages, string $reason, ?ConstraintInterface $constraint = null): array
@@ -522,12 +597,14 @@ private static function computeCheckForLowerPrioRepo(Pool $pool, bool $isVerbose
}
}
- if ($higherRepoPackages) {
+ assert(null !== $nextRepo);
+
+ if (\count($higherRepoPackages) > 0) {
$topPackage = reset($higherRepoPackages);
if ($topPackage instanceof RootPackageInterface) {
return [
"- Root composer.json requires $packageName".self::constraintToText($constraint).', it is ',
- 'satisfiable by '.self::getPackageList($nextRepoPackages, $isVerbose, $pool, $constraint).' from '.$nextRepo->getRepoName().' but '.$topPackage->getPrettyName().' is the root package and cannot be modified. See https://getcomposer.org/dep-on-root for details and assistance.',
+ 'satisfiable by '.self::getPackageList($nextRepoPackages, $isVerbose, $pool, $constraint).' from '.$nextRepo->getRepoName().' but '.$topPackage->getPrettyName().' '.$topPackage->getPrettyVersion().' is the root package and cannot be modified. See https://getcomposer.org/dep-on-root for details and assistance.',
];
}
}
@@ -570,6 +647,25 @@ protected static function constraintToText(?ConstraintInterface $constraint = nu
return ' ' . $constraint->getPrettyString() . ' (exact version match: ' . (count($versions) > 1 ? implode(', ', array_slice($versions, 0, -1)) . ' or ' . end($versions) : $versions[0]) . ')';
}
- return $constraint ? ' '.$constraint->getPrettyString() : '';
+ return $constraint !== null ? ' '.$constraint->getPrettyString() : '';
+ }
+
+ private static function getProvidersList(RepositorySet $repositorySet, string $packageName, int $maxProviders): ?string
+ {
+ $providers = $repositorySet->getProviders($packageName);
+ if (\count($providers) > 0) {
+ $providersStr = implode(array_map(static function ($p): string {
+ $description = $p['description'] !== '' && $p['description'] !== null ? ' '.substr($p['description'], 0, 100) : '';
+
+ return ' - '.$p['name'].$description."\n";
+ }, count($providers) > $maxProviders + 1 ? array_slice($providers, 0, $maxProviders) : $providers));
+ if (count($providers) > $maxProviders + 1) {
+ $providersStr .= ' ... and '.(count($providers) - $maxProviders).' more.'."\n";
+ }
+
+ return $providersStr;
+ }
+
+ return null;
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Request.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Request.php
index 300093f04..b11f4e1f2 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Request.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Request.php
@@ -190,7 +190,7 @@ public function getFixedOrLockedPackages(): array
}
/**
- * @return array
+ * @return ($packageIds is true ? array : array)
*
* @TODO look into removing the packageIds option, the only place true is used
* is for the installed map in the solver problems.
@@ -201,7 +201,7 @@ public function getPresentMap(bool $packageIds = false): array
{
$presentMap = [];
- if ($this->lockedRepository) {
+ if ($this->lockedRepository !== null) {
foreach ($this->lockedRepository->getPackages() as $package) {
$presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package;
}
@@ -215,7 +215,7 @@ public function getPresentMap(bool $packageIds = false): array
}
/**
- * @return BasePackage[]
+ * @return array
*/
public function getFixedPackagesMap(): array
{
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule.php
index 1b2f1aa95..8dde02b37 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule.php
@@ -137,12 +137,12 @@ public function enable(): void
public function isDisabled(): bool
{
- return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
+ return 0 !== (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
}
public function isEnabled(): bool
{
- return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
+ return 0 === (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
}
abstract public function isAssertion(): bool;
@@ -153,7 +153,7 @@ public function isCausedByLock(RepositorySet $repositorySet, Request $request, P
if (PlatformRepository::isPlatformPackage($this->getReasonData()->getTarget())) {
return false;
}
- if ($request->getLockedRepository()) {
+ if ($request->getLockedRepository() !== null) {
foreach ($request->getLockedRepository()->getPackages() as $package) {
if ($package->getName() === $this->getReasonData()->getTarget()) {
if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
@@ -176,7 +176,7 @@ public function isCausedByLock(RepositorySet $repositorySet, Request $request, P
if (PlatformRepository::isPlatformPackage($this->getReasonData()['packageName'])) {
return false;
}
- if ($request->getLockedRepository()) {
+ if ($request->getLockedRepository() !== null) {
foreach ($request->getLockedRepository()->getPackages() as $package) {
if ($package->getName() === $this->getReasonData()['packageName']) {
if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
@@ -215,7 +215,7 @@ public function getSourcePackage(Pool $pool): BasePackage
return $package2;
case self::RULE_PACKAGE_REQUIRES:
- $sourceLiteral = array_shift($literals);
+ $sourceLiteral = $literals[0];
$sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral));
return $sourcePackage;
@@ -240,14 +240,14 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
$constraint = $reasonData['constraint'];
$packages = $pool->whatProvides($packageName, $constraint);
- if (!$packages) {
+ if (0 === \count($packages)) {
return 'No package found to satisfy root composer.json require '.$packageName.' '.$constraint->getPrettyString();
}
$packagesNonAlias = array_values(array_filter($packages, static function ($p): bool {
return !($p instanceof AliasPackage);
}));
- if (count($packagesNonAlias) === 1) {
+ if (\count($packagesNonAlias) === 1) {
$package = $packagesNonAlias[0];
if ($request->isLockedPackage($package)) {
return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion()." and an update of this package was not requested.";
@@ -305,6 +305,7 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
return $package2->getPrettyString().' conflicts with '.$conflictTarget.'.';
case self::RULE_PACKAGE_REQUIRES:
+ assert(\count($literals) > 0);
$sourceLiteral = array_shift($literals);
$sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral));
$reasonData = $this->getReasonData();
@@ -315,7 +316,7 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
}
$text = $reasonData->getPrettyString($sourcePackage);
- if ($requires) {
+ if (\count($requires) > 0) {
$text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires, $isVerbose, $reasonData->getConstraint()) . '.';
} else {
$targetName = $reasonData->getTarget();
@@ -333,19 +334,18 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
$package = $pool->literalToPackage($literal);
$packageNames[$package->getName()] = true;
}
+ unset($literal);
$replacedName = $this->getReasonData();
- if (count($packageNames) > 1) {
- $reason = null;
-
+ if (\count($packageNames) > 1) {
if (!isset($packageNames[$replacedName])) {
- $reason = 'They '.(count($literals) === 2 ? 'both' : 'all').' replace '.$replacedName.' and thus cannot coexist.';
+ $reason = 'They '.(\count($literals) === 2 ? 'both' : 'all').' replace '.$replacedName.' and thus cannot coexist.';
} else {
$replacerNames = $packageNames;
unset($replacerNames[$replacedName]);
$replacerNames = array_keys($replacerNames);
- if (count($replacerNames) === 1) {
+ if (\count($replacerNames) === 1) {
$reason = $replacerNames[0] . ' replaces ';
} else {
$reason = '['.implode(', ', $replacerNames).'] replace ';
@@ -363,7 +363,7 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
}
}
- if ($installedPackages && $removablePackages) {
+ if (\count($installedPackages) > 0 && \count($removablePackages) > 0) {
return $this->formatPackagesUnique($pool, $removablePackages, $isVerbose, null, true).' cannot be installed as that would require removing '.$this->formatPackagesUnique($pool, $installedPackages, $isVerbose, null, true).'. '.$reason;
}
@@ -381,7 +381,7 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
// }
$learnedString = ' (conflict analysis result)';
- if (count($literals) === 1) {
+ if (\count($literals) === 1) {
$ruleText = $pool->literalToPrettyString($literals[0], $installedMap);
} else {
$groups = [];
@@ -397,7 +397,7 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
}
$ruleTexts = [];
foreach ($groups as $group => $packages) {
- $ruleTexts[] = $group . (count($packages) > 1 ? ' one of' : '').' ' . $this->formatPackagesUnique($pool, $packages, $isVerbose);
+ $ruleTexts[] = $group . (\count($packages) > 1 ? ' one of' : '').' ' . $this->formatPackagesUnique($pool, $packages, $isVerbose);
}
$ruleText = implode(' | ', $ruleTexts);
@@ -439,14 +439,13 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
}
/**
- * @param array $packages An array containing packages or literals
+ * @param array $literalsOrPackages An array containing packages or literals
*/
- protected function formatPackagesUnique(Pool $pool, array $packages, bool $isVerbose, ?ConstraintInterface $constraint = null, bool $useRemovedVersionGroup = false): string
+ protected function formatPackagesUnique(Pool $pool, array $literalsOrPackages, bool $isVerbose, ?ConstraintInterface $constraint = null, bool $useRemovedVersionGroup = false): string
{
- foreach ($packages as $index => $package) {
- if (!\is_object($package)) {
- $packages[$index] = $pool->literalToPackage($package);
- }
+ $packages = [];
+ foreach ($literalsOrPackages as $package) {
+ $packages[] = \is_object($package) ? $package : $pool->literalToPackage($package);
}
return Problem::getPackageList($packages, $isVerbose, $pool, $constraint, $useRemovedVersionGroup);
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php
index 17bfaf8ce..33d0ed0be 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php
@@ -43,7 +43,7 @@ public function __construct(int $literal1, int $literal2, $reason, $reasonData)
}
/**
- * @return list
+ * @return non-empty-list
*/
public function getLiterals(): array
{
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSet.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSet.php
index 4a406238a..cca9eb123 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSet.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSet.php
@@ -179,7 +179,7 @@ public function getPrettyString(?RepositorySet $repositorySet = null, ?Request $
foreach ($this->rules as $type => $rules) {
$string .= str_pad(self::TYPES[$type], 8, ' ') . ": ";
foreach ($rules as $rule) {
- $string .= ($repositorySet && $request && $pool ? $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose) : $rule)."\n";
+ $string .= ($repositorySet !== null && $request !== null && $pool !== null ? $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose) : $rule)."\n";
}
$string .= "\n\n";
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php
index 69d119134..08c874ff7 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php
@@ -56,7 +56,7 @@ public function __construct(PolicyInterface $policy, Pool $pool)
*
* @phpstan-param ReasonData $reasonData
*/
- protected function createRequireRule(BasePackage $package, array $providers, $reason, $reasonData = null): ?Rule
+ protected function createRequireRule(BasePackage $package, array $providers, $reason, $reasonData): ?Rule
{
$literals = [-$package->id];
@@ -77,7 +77,7 @@ protected function createRequireRule(BasePackage $package, array $providers, $re
* The rule is (A|B|C) with A, B and C different packages. If the given
* set of packages is empty an impossible rule is generated.
*
- * @param BasePackage[] $packages The set of packages to choose from
+ * @param non-empty-array $packages The set of packages to choose from
* @param Rule::RULE_* $reason A RULE_* constant describing the reason for
* generating this rule
* @param mixed $reasonData Additional data like the root require or fix request info
@@ -109,7 +109,7 @@ protected function createInstallOneOfRule(array $packages, $reason, $reasonData)
*
* @phpstan-param ReasonData $reasonData
*/
- protected function createRule2Literals(BasePackage $issuer, BasePackage $provider, $reason, $reasonData = null): ?Rule
+ protected function createRule2Literals(BasePackage $issuer, BasePackage $provider, $reason, $reasonData): ?Rule
{
// ignore self conflict
if ($issuer === $provider) {
@@ -120,7 +120,7 @@ protected function createRule2Literals(BasePackage $issuer, BasePackage $provide
}
/**
- * @param BasePackage[] $packages
+ * @param non-empty-array $packages
* @param Rule::RULE_* $reason A RULE_* constant
* @param mixed $reasonData
*
@@ -151,7 +151,7 @@ protected function createMultiConflictRule(array $packages, $reason, $reasonData
*/
private function addRule($type, ?Rule $newRule = null): void
{
- if (!$newRule) {
+ if (null === $newRule) {
return;
}
@@ -276,7 +276,7 @@ protected function addRulesForRequest(Request $request, PlatformRequirementFilte
}
$packages = $this->pool->whatProvides($packageName, $constraint);
- if ($packages) {
+ if (\count($packages) > 0) {
foreach ($packages as $package) {
$this->addRulesForPackage($package, $platformRequirementFilter);
}
@@ -307,7 +307,7 @@ protected function addRulesForRootAliases(PlatformRequirementFilterInterface $pl
public function getRulesFor(Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null): RuleSet
{
- $platformRequirementFilter = $platformRequirementFilter ?: PlatformRequirementFilterFactory::ignoreNothing();
+ $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing();
$this->addRulesForRequest($request, $platformRequirementFilter);
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php
index 2bf67f55b..3b8383d47 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php
@@ -14,7 +14,7 @@
/**
* @author Nils Adermann
- * @implements \Iterator
+ * @implements \Iterator
*/
class RuleSetIterator implements \Iterator
{
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Solver.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Solver.php
index 373e8325d..b8aa847d1 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Solver.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Solver.php
@@ -43,7 +43,7 @@ class Solver
/** @var int */
protected $propagateIndex;
- /** @var mixed[] */
+ /** @var array, int}> */
protected $branches = [];
/** @var Problem[] */
protected $problems = [];
@@ -109,7 +109,7 @@ private function makeAssertionRuleDecisions(): void
$conflict = $this->decisions->decisionRule($literal);
- if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
+ if (RuleSet::TYPE_PACKAGE === $conflict->getType()) {
$problem = new Problem();
$problem->addRule($rule);
@@ -164,7 +164,7 @@ protected function checkForRootRequireProblems(Request $request, PlatformRequire
$constraint = $platformRequirementFilter->filterConstraint($packageName, $constraint);
}
- if (!$this->pool->whatProvides($packageName, $constraint)) {
+ if (0 === \count($this->pool->whatProvides($packageName, $constraint))) {
$problem = new Problem();
$problem->addRule(new GenericRule([], Rule::RULE_ROOT_REQUIRE, ['packageName' => $packageName, 'constraint' => $constraint]));
$this->problems[] = $problem;
@@ -174,7 +174,7 @@ protected function checkForRootRequireProblems(Request $request, PlatformRequire
public function solve(Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null): LockTransaction
{
- $platformRequirementFilter = $platformRequirementFilter ?: PlatformRequirementFilterFactory::ignoreNothing();
+ $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing();
$this->setupFixedMap($request);
@@ -199,7 +199,7 @@ public function solve(Request $request, ?PlatformRequirementFilterInterface $pla
$this->io->writeError('', true, IOInterface::DEBUG);
$this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
- if ($this->problems) {
+ if (\count($this->problems) > 0) {
throw new SolverProblemsException($this->problems, $this->learnedPool);
}
@@ -227,7 +227,7 @@ protected function propagate(int $level): ?Rule
$this->propagateIndex++;
- if ($conflict) {
+ if ($conflict !== null) {
return $conflict;
}
}
@@ -257,7 +257,7 @@ private function revert(int $level): void
$this->propagateIndex = \count($this->decisions);
}
- while (!empty($this->branches) && $this->branches[\count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
+ while (\count($this->branches) > 0 && $this->branches[\count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
array_pop($this->branches);
}
}
@@ -274,10 +274,8 @@ private function revert(int $level): void
* rule (always unit) and re-propagate.
*
* returns the new solver level or 0 if unsolvable
- *
- * @param string|int $literal
*/
- private function setPropagateLearn(int $level, $literal, Rule $rule): int
+ private function setPropagateLearn(int $level, int $literal, Rule $rule): int
{
$level++;
@@ -291,7 +289,9 @@ private function setPropagateLearn(int $level, $literal, Rule $rule): int
}
if ($level === 1) {
- return $this->analyzeUnsolvable($rule);
+ $this->analyzeUnsolvable($rule);
+
+ return 0;
}
// conflict
@@ -322,7 +322,7 @@ private function setPropagateLearn(int $level, $literal, Rule $rule): int
}
/**
- * @param int[] $decisionQueue
+ * @param non-empty-list $decisionQueue
*/
private function selectAndInstall(int $level, array $decisionQueue, Rule $rule): int
{
@@ -332,7 +332,7 @@ private function selectAndInstall(int $level, array $decisionQueue, Rule $rule):
$selectedLiteral = array_shift($literals);
// if there are multiple candidates, then branch
- if (\count($literals)) {
+ if (\count($literals) > 0) {
$this->branches[] = [$literals, $level];
}
@@ -349,7 +349,8 @@ protected function analyze(int $level, Rule $rule): array
$num = 0;
$l1num = 0;
$seen = [];
- $learnedLiterals = [null];
+ $learnedLiteral = null;
+ $otherLearnedLiterals = [];
$decisionId = \count($this->decisions);
@@ -382,7 +383,7 @@ protected function analyze(int $level, Rule $rule): array
$num++;
} else {
// not level1 or conflict level, add to new rule
- $learnedLiterals[] = $literal;
+ $otherLearnedLiterals[] = $literal;
if ($l > $ruleLevel) {
$ruleLevel = $l;
@@ -423,16 +424,14 @@ protected function analyze(int $level, Rule $rule): array
if ($literal < 0) {
$this->testFlagLearnedPositiveLiteral = true;
}
- $learnedLiterals[0] = -$literal;
+ $learnedLiteral = -$literal;
- if (!$l1num) {
+ if (0 === $l1num) {
break 2;
}
- foreach ($learnedLiterals as $i => $learnedLiteral) {
- if ($i !== 0) {
- unset($seen[abs($learnedLiteral)]);
- }
+ foreach ($otherLearnedLiterals as $otherLiteral) {
+ unset($seen[abs($otherLiteral)]);
}
// only level 1 marks left
$l1num++;
@@ -442,24 +441,24 @@ protected function analyze(int $level, Rule $rule): array
$rule = $decision[Decisions::DECISION_REASON];
if ($rule instanceof MultiConflictRule) {
- // there is only ever exactly one positive decision in a multiconflict rule
- foreach ($rule->getLiterals() as $literal) {
- if (!isset($seen[abs($literal)]) && $this->decisions->satisfy(-$literal)) {
+ // there is only ever exactly one positive decision in a MultiConflictRule
+ foreach ($rule->getLiterals() as $ruleLiteral) {
+ if (!isset($seen[abs($ruleLiteral)]) && $this->decisions->satisfy(-$ruleLiteral)) {
$this->learnedPool[\count($this->learnedPool) - 1][] = $rule;
- $l = $this->decisions->decisionLevel($literal);
+ $l = $this->decisions->decisionLevel($ruleLiteral);
if (1 === $l) {
$l1num++;
} elseif ($level === $l) {
$num++;
} else {
// not level1 or conflict level, add to new rule
- $learnedLiterals[] = $literal;
+ $otherLearnedLiterals[] = $ruleLiteral;
if ($l > $ruleLevel) {
$ruleLevel = $l;
}
}
- $seen[abs($literal)] = true;
+ $seen[abs($ruleLiteral)] = true;
break;
}
}
@@ -475,15 +474,16 @@ protected function analyze(int $level, Rule $rule): array
$why = \count($this->learnedPool) - 1;
- if (null === $learnedLiterals[0]) {
+ if (null === $learnedLiteral) {
throw new SolverBugException(
"Did not find a learnable literal in analyzed rule $analyzedRule."
);
}
- $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
+ array_unshift($otherLearnedLiterals, $learnedLiteral);
+ $newRule = new GenericRule($otherLearnedLiterals, Rule::RULE_LEARNED, $why);
- return [$learnedLiterals[0], $ruleLevel, $newRule, $why];
+ return [$learnedLiteral, $ruleLevel, $newRule, $why];
}
/**
@@ -516,7 +516,7 @@ private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule, arr
$problem->addRule($conflictRule);
}
- private function analyzeUnsolvable(Rule $conflictRule): int
+ private function analyzeUnsolvable(Rule $conflictRule): void
{
$problem = new Problem();
$problem->addRule($conflictRule);
@@ -539,10 +539,10 @@ private function analyzeUnsolvable(Rule $conflictRule): int
}
foreach ($this->decisions as $decision) {
- $literal = $decision[Decisions::DECISION_LITERAL];
+ $decisionLiteral = $decision[Decisions::DECISION_LITERAL];
// skip literals that are not in this rule
- if (!isset($seen[abs($literal)])) {
+ if (!isset($seen[abs($decisionLiteral)])) {
continue;
}
@@ -552,7 +552,6 @@ private function analyzeUnsolvable(Rule $conflictRule): int
$this->analyzeUnsolvableRule($problem, $why, $ruleSeen);
$literals = $why->getLiterals();
-
foreach ($literals as $literal) {
// skip the one true literal
if ($this->decisions->satisfy($literal)) {
@@ -561,8 +560,6 @@ private function analyzeUnsolvable(Rule $conflictRule): int
$seen[abs($literal)] = true;
}
}
-
- return 0;
}
private function runSat(): void
@@ -586,9 +583,7 @@ private function runSat(): void
if (1 === $level) {
$conflictRule = $this->propagate($level);
if (null !== $conflictRule) {
- if ($this->analyzeUnsolvable($conflictRule)) {
- continue;
- }
+ $this->analyzeUnsolvable($conflictRule);
return;
}
@@ -612,7 +607,7 @@ private function runSat(): void
}
}
- if ($noneSatisfied && \count($decisionQueue)) {
+ if ($noneSatisfied && \count($decisionQueue) > 0) {
// if any of the options in the decision queue are fixed, only use those
$prunedQueue = [];
foreach ($decisionQueue as $literal) {
@@ -620,12 +615,12 @@ private function runSat(): void
$prunedQueue[] = $literal;
}
}
- if (!empty($prunedQueue)) {
+ if (\count($prunedQueue) > 0) {
$decisionQueue = $prunedQueue;
}
}
- if ($noneSatisfied && \count($decisionQueue)) {
+ if ($noneSatisfied && \count($decisionQueue) > 0) {
$oLevel = $level;
$level = $this->selectAndInstall($level, $decisionQueue, $rule);
@@ -719,7 +714,7 @@ private function runSat(): void
}
// minimization step
- if (\count($this->branches)) {
+ if (\count($this->branches) > 0) {
$lastLiteral = null;
$lastLevel = null;
$lastBranchIndex = 0;
@@ -729,7 +724,7 @@ private function runSat(): void
[$literals, $l] = $this->branches[$i];
foreach ($literals as $offset => $literal) {
- if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
+ if ($literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
$lastLiteral = $literal;
$lastBranchIndex = $i;
$lastBranchOffset = $offset;
@@ -738,7 +733,8 @@ private function runSat(): void
}
}
- if ($lastLiteral) {
+ if ($lastLiteral !== null) {
+ assert($lastLevel !== null);
unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
$level = $lastLevel;
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php
index 5870c0cae..bd76e4fa3 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php
@@ -38,7 +38,7 @@ public function __construct(array $problems, array $learnedPool)
$this->problems = $problems;
$this->learnedPool = $learnedPool;
- parent::__construct('Failed resolving dependencies with '.count($problems).' problems, call getPrettyString to get formatted details', self::ERROR_DEPENDENCY_RESOLUTION_FAILED);
+ parent::__construct('Failed resolving dependencies with '.\count($problems).' problems, call getPrettyString to get formatted details', self::ERROR_DEPENDENCY_RESOLUTION_FAILED);
}
public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, bool $isVerbose, bool $isDevExtraction = false): string
@@ -63,11 +63,11 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
}
$hints = [];
- if (!$isDevExtraction && (strpos($text, 'could not be found') || strpos($text, 'no matching package found'))) {
+ if (!$isDevExtraction && (str_contains($text, 'could not be found') || str_contains($text, 'no matching package found'))) {
$hints[] = "Potential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead for further common problems.";
}
- if (!empty($missingExtensions)) {
+ if (\count($missingExtensions) > 0) {
$hints[] = $this->createExtensionHint($missingExtensions);
}
@@ -75,17 +75,17 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
$hints[] = "Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.";
}
- if (strpos($text, 'found composer-plugin-api[2.0.0] but it does not match') && strpos($text, '- ocramius/package-versions')) {
+ if (str_contains($text, 'found composer-plugin-api[2.0.0] but it does not match') && str_contains($text, '- ocramius/package-versions')) {
$hints[] = "ocramius/package-versions only provides support for Composer 2 in 1.8+, which requires PHP 7.4.\nIf you can not upgrade PHP you can require composer/package-versions-deprecated to resolve this with PHP 7.0+.";
}
if (!class_exists('PHPUnit\Framework\TestCase', false)) {
- if (strpos($text, 'found composer-plugin-api[2.0.0] but it does not match')) {
+ if (str_contains($text, 'found composer-plugin-api[2.0.0] but it does not match')) {
$hints[] = "You are using Composer 2, which some of your plugins seem to be incompatible with. Make sure you update your plugins or report a plugin-issue to ask them to support Composer 2.";
}
}
- if ($hints) {
+ if (\count($hints) > 0) {
$text .= "\n" . implode("\n\n", $hints);
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Transaction.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Transaction.php
index ef6860c11..3443dd768 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Transaction.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Transaction.php
@@ -123,7 +123,7 @@ protected function calculateOperations(): array
$visited = [];
$processed = [];
- while (!empty($stack)) {
+ while (\count($stack) > 0) {
$package = array_pop($stack);
if (isset($processed[spl_object_hash($package)])) {
@@ -283,17 +283,18 @@ private function movePluginsToFront(array $operations): array
continue;
}
- $isDownloadsModifyingPlugin = $package->getType() === 'composer-plugin' && ($extra = $package->getExtra()) && isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === true;
+ $extra = $package->getExtra();
+ $isDownloadsModifyingPlugin = $package->getType() === 'composer-plugin' && isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === true;
// is this a downloads modifying plugin or a dependency of one?
- if ($isDownloadsModifyingPlugin || count(array_intersect($package->getNames(), $dlModifyingPluginRequires))) {
+ if ($isDownloadsModifyingPlugin || \count(array_intersect($package->getNames(), $dlModifyingPluginRequires)) > 0) {
// get the package's requires, but filter out any platform requirements
$requires = array_filter(array_keys($package->getRequires()), static function ($req): bool {
return !PlatformRepository::isPlatformPackage($req);
});
// is this a plugin with no meaningful dependencies?
- if ($isDownloadsModifyingPlugin && !count($requires)) {
+ if ($isDownloadsModifyingPlugin && 0 === \count($requires)) {
// plugins with no dependencies go to the very front
array_unshift($dlModifyingPluginsNoDeps, $op);
} else {
@@ -311,14 +312,14 @@ private function movePluginsToFront(array $operations): array
$isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
// is this a plugin or a dependency of a plugin?
- if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
+ if ($isPlugin || \count(array_intersect($package->getNames(), $pluginRequires)) > 0) {
// get the package's requires, but filter out any platform requirements
$requires = array_filter(array_keys($package->getRequires()), static function ($req): bool {
return !PlatformRepository::isPlatformPackage($req);
});
// is this a plugin with no meaningful dependencies?
- if ($isPlugin && !count($requires)) {
+ if ($isPlugin && 0 === \count($requires)) {
// plugins with no dependencies go to the very front
array_unshift($pluginsNoDeps, $op);
} else {
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/ArchiveDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/ArchiveDownloader.php
index 6de51ee58..ff132e28b 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/ArchiveDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/ArchiveDownloader.php
@@ -68,7 +68,7 @@ public function install(PackageInterface $package, string $path, bool $output =
}
do {
- $temporaryDir = $vendorDir.'/composer/'.substr(md5(uniqid('', true)), 0, 8);
+ $temporaryDir = $vendorDir.'/composer/'.bin2hex(random_bytes(4));
} while (is_dir($temporaryDir));
$this->addCleanupPath($package, $temporaryDir);
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/FileDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/FileDownloader.php
index adf26785c..5f3b24279 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/FileDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/FileDownloader.php
@@ -126,7 +126,7 @@ public function download(PackageInterface $package, string $path, ?PackageInterf
}
$cacheKeyGenerator = static function (PackageInterface $package, $key): string {
- $cacheKey = sha1($key);
+ $cacheKey = hash('sha1', $key);
return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
};
@@ -350,7 +350,14 @@ public function install(PackageInterface $package, string $path, bool $output =
$this->io->writeError(" - " . InstallOperation::format($package));
}
- $this->filesystem->emptyDirectory($path);
+ $vendorDir = $this->config->get('vendor-dir');
+
+ // clean up the target directory, unless it contains the vendor dir, as the vendor dir contains
+ // the file to be installed. This is the case when installing with create-project in the current directory
+ // but in that case we ensure the directory is empty already in ProjectInstaller so no need to empty it here.
+ if (false === strpos($this->filesystem->normalizePath($vendorDir), $this->filesystem->normalizePath($path.DIRECTORY_SEPARATOR))) {
+ $this->filesystem->emptyDirectory($path);
+ }
$this->filesystem->ensureDirectoryExists($path);
$this->filesystem->rename($this->getFileName($package, $path), $path . '/' . $this->getDistPath($package, PATHINFO_BASENAME));
@@ -441,7 +448,7 @@ protected function getFileName(PackageInterface $package, string $path): string
$extension = $package->getDistType();
}
- return rtrim($this->config->get('vendor-dir') . '/composer/tmp-' . md5($package . spl_object_hash($package)) . '.' . $extension, '.');
+ return rtrim($this->config->get('vendor-dir') . '/composer/tmp-' . hash('md5', $package . spl_object_hash($package)) . '.' . $extension, '.');
}
/**
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/FossilDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/FossilDownloader.php
index 6634771dc..60c6ed49d 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/FossilDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/FossilDownloader.php
@@ -12,10 +12,12 @@
namespace Composer\Downloader;
+use Composer\Util\Platform;
use React\Promise\PromiseInterface;
use Composer\Package\PackageInterface;
use Composer\Pcre\Preg;
use Composer\Util\ProcessExecutor;
+use RuntimeException;
/**
* @author BohwaZ
@@ -38,22 +40,13 @@ protected function doInstall(PackageInterface $package, string $path, string $ur
// Ensure we are allowed to use this URL by config
$this->config->prohibitUrlByConfig($url, $this->io);
- $url = ProcessExecutor::escape($url);
- $ref = ProcessExecutor::escape($package->getSourceReference());
$repoFile = $path . '.fossil';
+ $realPath = Platform::realpath($path);
+
$this->io->writeError("Cloning ".$package->getSourceReference());
- $command = sprintf('fossil clone -- %s %s', $url, ProcessExecutor::escape($repoFile));
- if (0 !== $this->process->execute($command, $ignoredOutput)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
- $command = sprintf('fossil open --nested -- %s', ProcessExecutor::escape($repoFile));
- if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
- $command = sprintf('fossil update -- %s', $ref);
- if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
+ $this->execute(['fossil', 'clone', '--', $url, $repoFile]);
+ $this->execute(['fossil', 'open', '--nested', '--', $repoFile], $realPath);
+ $this->execute(['fossil', 'update', '--', (string) $package->getSourceReference()], $realPath);
return \React\Promise\resolve(null);
}
@@ -66,17 +59,15 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
// Ensure we are allowed to use this URL by config
$this->config->prohibitUrlByConfig($url, $this->io);
- $ref = ProcessExecutor::escape($target->getSourceReference());
$this->io->writeError(" Updating to ".$target->getSourceReference());
if (!$this->hasMetadataRepository($path)) {
throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
}
- $command = sprintf('fossil pull && fossil up %s', $ref);
- if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
+ $realPath = Platform::realpath($path);
+ $this->execute(['fossil', 'pull'], $realPath);
+ $this->execute(['fossil', 'up', (string) $target->getSourceReference()], $realPath);
return \React\Promise\resolve(null);
}
@@ -90,7 +81,7 @@ public function getLocalChanges(PackageInterface $package, string $path): ?strin
return null;
}
- $this->process->execute('fossil changes', $output, realpath($path));
+ $this->process->execute(['fossil', 'changes'], $output, Platform::realpath($path));
$output = trim($output);
@@ -102,11 +93,7 @@ public function getLocalChanges(PackageInterface $package, string $path): ?strin
*/
protected function getCommitLogs(string $fromReference, string $toReference, string $path): string
{
- $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', ProcessExecutor::escape($toReference));
-
- if (0 !== $this->process->execute($command, $output, realpath($path))) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
+ $this->execute(['fossil', 'timeline', '-t', 'ci', '-W', '0', '-n', '0', 'before', $toReference], Platform::realpath($path), $output);
$log = '';
$match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
@@ -121,6 +108,17 @@ protected function getCommitLogs(string $fromReference, string $toReference, str
return $log;
}
+ /**
+ * @param non-empty-list $command
+ * @throws \RuntimeException
+ */
+ private function execute(array $command, ?string $cwd = null, ?string &$output = null): void
+ {
+ if (0 !== $this->process->execute($command, $output, $cwd)) {
+ throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
+ }
+ }
+
/**
* @inheritDoc
*/
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/GitDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/GitDownloader.php
index 0840219d0..e54d95473 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/GitDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/GitDownloader.php
@@ -67,13 +67,13 @@ protected function doDownload(PackageInterface $package, string $path, string $u
GitUtil::cleanEnv();
- $cachePath = $this->config->get('cache-vcs-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', $url).'/';
+ $cachePath = $this->config->get('cache-vcs-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($url)).'/';
$gitVersion = GitUtil::getVersion($this->process);
// --dissociate option is only available since git 2.3.0-rc0
if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=') && Cache::isUsable($cachePath)) {
$this->io->writeError(" - Syncing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ") into cache");
- $this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
+ $this->io->writeError(sprintf(' Cloning to cache at %s', $cachePath), true, IOInterface::DEBUG);
$ref = $package->getSourceReference();
if ($this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref, $package->getPrettyVersion()) && is_dir($cachePath)) {
$this->cachedPackages[$package->getId()][$ref] = true;
@@ -92,26 +92,32 @@ protected function doInstall(PackageInterface $package, string $path, string $ur
{
GitUtil::cleanEnv();
$path = $this->normalizePath($path);
- $cachePath = $this->config->get('cache-vcs-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', $url).'/';
+ $cachePath = $this->config->get('cache-vcs-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($url)).'/';
$ref = $package->getSourceReference();
- $flag = Platform::isWindows() ? '/D ' : '';
if (!empty($this->cachedPackages[$package->getId()][$ref])) {
$msg = "Cloning ".$this->getShortHash($ref).' from cache';
- $cloneFlags = '--dissociate --reference %cachePath% ';
+ $cloneFlags = ['--dissociate', '--reference', $cachePath];
$transportOptions = $package->getTransportOptions();
if (isset($transportOptions['git']['single_use_clone']) && $transportOptions['git']['single_use_clone']) {
- $cloneFlags = '';
+ $cloneFlags = [];
}
- $command =
- 'git clone --no-checkout %cachePath% %path% ' . $cloneFlags
- . '&& cd '.$flag.'%path% '
- . '&& git remote set-url origin -- %sanitizedUrl% && git remote add composer -- %sanitizedUrl%';
+ $commands = [
+ array_merge(['git', 'clone', '--no-checkout', $cachePath, $path], $cloneFlags),
+ ['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%'],
+ ['git', 'remote', 'add', 'composer', '--', '%sanitizedUrl%'],
+ ];
} else {
$msg = "Cloning ".$this->getShortHash($ref);
- $command = 'git clone --no-checkout -- %url% %path% && cd '.$flag.'%path% && git remote add composer -- %url% && git fetch composer && git remote set-url origin -- %sanitizedUrl% && git remote set-url composer -- %sanitizedUrl%';
+ $commands = [
+ array_merge(['git', 'clone', '--no-checkout', '--', '%url%', $path]),
+ ['git', 'remote', 'add', 'composer', '--', '%url%'],
+ ['git', 'fetch', 'composer'],
+ ['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%'],
+ ['git', 'remote', 'set-url', 'composer', '--', '%sanitizedUrl%'],
+ ];
if (Platform::getEnv('COMPOSER_DISABLE_NETWORK')) {
throw new \RuntimeException('The required git reference for '.$package->getName().' is not in cache and network is disabled, aborting');
}
@@ -119,20 +125,8 @@ protected function doInstall(PackageInterface $package, string $path, string $ur
$this->io->writeError($msg);
- $commandCallable = static function (string $url) use ($path, $command, $cachePath): string {
- return str_replace(
- ['%url%', '%path%', '%cachePath%', '%sanitizedUrl%'],
- [
- ProcessExecutor::escape($url),
- ProcessExecutor::escape($path),
- ProcessExecutor::escape($cachePath),
- ProcessExecutor::escape(Preg::replace('{://([^@]+?):(.+?)@}', '://', $url)),
- ],
- $command
- );
- };
+ $this->gitUtil->runCommands($commands, $url, $path, true);
- $this->gitUtil->runCommand($commandCallable, $url, $path, true);
$sourceUrl = $package->getSourceUrl();
if ($url !== $sourceUrl && $sourceUrl !== null) {
$this->updateOriginUrl($path, $sourceUrl);
@@ -161,15 +155,15 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
}
- $cachePath = $this->config->get('cache-vcs-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', $url).'/';
+ $cachePath = $this->config->get('cache-vcs-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($url)).'/';
$ref = $target->getSourceReference();
if (!empty($this->cachedPackages[$target->getId()][$ref])) {
$msg = "Checking out ".$this->getShortHash($ref).' from cache';
- $command = '(git rev-parse --quiet --verify %ref% || (git remote set-url composer -- %cachePath% && git fetch composer && git fetch --tags composer)) && git remote set-url composer -- %sanitizedUrl%';
+ $remoteUrl = $cachePath;
} else {
$msg = "Checking out ".$this->getShortHash($ref);
- $command = '(git remote set-url composer -- %url% && git rev-parse --quiet --verify %ref% || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- %sanitizedUrl%';
+ $remoteUrl = '%url%';
if (Platform::getEnv('COMPOSER_DISABLE_NETWORK')) {
throw new \RuntimeException('The required git reference for '.$target->getName().' is not in cache and network is disabled, aborting');
}
@@ -177,20 +171,19 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
$this->io->writeError($msg);
- $commandCallable = static function ($url) use ($ref, $command, $cachePath): string {
- return str_replace(
- ['%url%', '%ref%', '%cachePath%', '%sanitizedUrl%'],
- [
- ProcessExecutor::escape($url),
- ProcessExecutor::escape($ref.'^{commit}'),
- ProcessExecutor::escape($cachePath),
- ProcessExecutor::escape(Preg::replace('{://([^@]+?):(.+?)@}', '://', $url)),
- ],
- $command
- );
- };
+ if (0 !== $this->process->execute(['git', 'rev-parse', '--quiet', '--verify', $ref.'^{commit}'], $output, $path)) {
+ $commands = [
+ ['git', 'remote', 'set-url', 'composer', '--', $remoteUrl],
+ ['git', 'fetch', 'composer'],
+ ['git', 'fetch', '--tags', 'composer'],
+ ];
+
+ $this->gitUtil->runCommands($commands, $url, $path);
+ }
+
+ $command = ['git', 'remote', 'set-url', 'composer', '--', '%sanitizedUrl%'];
+ $this->gitUtil->runCommands([$command], $url, $path);
- $this->gitUtil->runCommand($commandCallable, $url, $path);
if ($newRef = $this->updateToCommit($target, $path, (string) $ref, $target->getPrettyVersion())) {
if ($target->getDistReference() === $target->getSourceReference()) {
$target->setDistReference($newRef);
@@ -200,7 +193,7 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
$updateOriginUrl = false;
if (
- 0 === $this->process->execute('git remote -v', $output, $path)
+ 0 === $this->process->execute(['git', 'remote', '-v'], $output, $path)
&& Preg::isMatch('{^origin\s+(?P\S+)}m', $output, $originMatch)
&& Preg::isMatch('{^composer\s+(?P\S+)}m', $output, $composerMatch)
) {
@@ -225,9 +218,9 @@ public function getLocalChanges(PackageInterface $package, string $path): ?strin
return null;
}
- $command = 'git status --porcelain --untracked-files=no';
+ $command = ['git', 'status', '--porcelain', '--untracked-files=no'];
if (0 !== $this->process->execute($command, $output, $path)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+ throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
}
$output = trim($output);
@@ -243,9 +236,9 @@ public function getUnpushedChanges(PackageInterface $package, string $path): ?st
return null;
}
- $command = 'git show-ref --head -d';
+ $command = ['git', 'show-ref', '--head', '-d'];
if (0 !== $this->process->execute($command, $output, $path)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+ throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
}
$refs = trim($output);
@@ -255,7 +248,7 @@ public function getUnpushedChanges(PackageInterface $package, string $path): ?st
}
$headRef = $match[1];
- if (!Preg::isMatchAllStrictGroups('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
+ if (!Preg::isMatchAllStrictGroups('{^'.preg_quote($headRef).' refs/heads/(.+)$}mi', $refs, $matches)) {
// not on a branch, we are either on a not-modified tag or some sort of detached head, so skip this
return null;
}
@@ -294,9 +287,9 @@ public function getUnpushedChanges(PackageInterface $package, string $path): ?st
$unpushedChanges = null;
}
foreach ($remoteBranches as $remoteBranch) {
- $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
+ $command = ['git', 'diff', '--name-status', $remoteBranch.'...'.$branch, '--'];
if (0 !== $this->process->execute($command, $output, $path)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+ throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
}
$output = trim($output);
@@ -310,12 +303,12 @@ public function getUnpushedChanges(PackageInterface $package, string $path): ?st
// first pass and we found unpushed changes, fetch from all remotes to make sure we have up to date
// remotes and then try again as outdated remotes can sometimes cause false-positives
if ($unpushedChanges && $i === 0) {
- $this->process->execute('git fetch --all', $output, $path);
+ $this->process->execute(['git', 'fetch', '--all'], $output, $path);
// update list of refs after fetching
- $command = 'git show-ref --head -d';
+ $command = ['git', 'show-ref', '--head', '-d'];
if (0 !== $this->process->execute($command, $output, $path)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+ throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
}
$refs = trim($output);
}
@@ -425,7 +418,7 @@ protected function reapplyChanges(string $path): void
if (!empty($this->hasStashedChanges[$path])) {
unset($this->hasStashedChanges[$path]);
$this->io->writeError(' Re-applying stashed changes');
- if (0 !== $this->process->execute('git stash pop', $output, $path)) {
+ if (0 !== $this->process->execute(['git', 'stash', 'pop'], $output, $path)) {
throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
}
}
@@ -441,18 +434,29 @@ protected function reapplyChanges(string $path): void
*/
protected function updateToCommit(PackageInterface $package, string $path, string $reference, string $prettyVersion): ?string
{
- $force = !empty($this->hasDiscardedChanges[$path]) || !empty($this->hasStashedChanges[$path]) ? '-f ' : '';
+ $force = !empty($this->hasDiscardedChanges[$path]) || !empty($this->hasStashedChanges[$path]) ? ['-f'] : [];
// This uses the "--" sequence to separate branch from file parameters.
//
// Otherwise git tries the branch name as well as file name.
// If the non-existent branch is actually the name of a file, the file
// is checked out.
- $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
+
$branch = Preg::replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $prettyVersion);
+ /**
+ * @var \Closure(non-empty-list): bool $execute
+ * @phpstan-ignore varTag.nativeType
+ */
+ $execute = function (array $command) use (&$output, $path) {
+ /** @var non-empty-list $command */
+ $output = '';
+
+ return 0 === $this->process->execute($command, $output, $path);
+ };
+
$branches = null;
- if (0 === $this->process->execute('git branch -r', $output, $path)) {
+ if ($execute(['git', 'branch', '-r'])) {
$branches = $output;
}
@@ -462,8 +466,10 @@ protected function updateToCommit(PackageInterface $package, string $path, strin
&& null !== $branches
&& Preg::isMatch('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
) {
- $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
- if (0 === $this->process->execute($command, $output, $path)) {
+ $command1 = array_merge(['git', 'checkout'], $force, ['-B', $branch, 'composer/'.$reference, '--']);
+ $command2 = ['git', 'reset', '--hard', 'composer/'.$reference, '--'];
+
+ if ($execute($command1) && $execute($command2)) {
return null;
}
}
@@ -475,17 +481,18 @@ protected function updateToCommit(PackageInterface $package, string $path, strin
$branch = 'v' . $branch;
}
- $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
- $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
- $resetCommand = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
+ $command = ['git', 'checkout', $branch, '--'];
+ $fallbackCommand = array_merge(['git', 'checkout'], $force, ['-B', $branch, 'composer/'.$branch, '--']);
+ $resetCommand = ['git', 'reset', '--hard', $reference, '--'];
- if (0 === $this->process->execute("($command || $fallbackCommand) && $resetCommand", $output, $path)) {
+ if (($execute($command) || $execute($fallbackCommand)) && $execute($resetCommand)) {
return null;
}
}
- $command = sprintf($template, ProcessExecutor::escape($gitRef));
- if (0 === $this->process->execute($command, $output, $path)) {
+ $command1 = array_merge(['git', 'checkout'], $force, [$gitRef, '--']);
+ $command2 = ['git', 'reset', '--hard', $gitRef, '--'];
+ if ($execute($command1) && $execute($command2)) {
return null;
}
@@ -497,12 +504,14 @@ protected function updateToCommit(PackageInterface $package, string $path, strin
$exceptionExtra = "\nIt looks like the commit hash is not available in the repository, maybe ".($package->isDev() ? 'the commit was removed from the branch' : 'the tag was recreated').'? Run "composer update '.$package->getPrettyName().'" to resolve this.';
}
+ $command = implode(' ', $command1). ' && '.implode(' ', $command2);
+
throw new \RuntimeException(Url::sanitize('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput() . $exceptionExtra));
}
protected function updateOriginUrl(string $path, string $url): void
{
- $this->process->execute(sprintf('git remote set-url origin -- %s', ProcessExecutor::escape($url)), $output, $path);
+ $this->process->execute(['git', 'remote', 'set-url', 'origin', '--', $url], $output, $path);
$this->setPushUrl($path, $url);
}
@@ -515,7 +524,7 @@ protected function setPushUrl(string $path, string $url): void
if (!in_array('ssh', $protocols, true)) {
$pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
}
- $cmd = sprintf('git remote set-url --push origin -- %s', ProcessExecutor::escape($pushUrl));
+ $cmd = ['git', 'remote', 'set-url', '--push', 'origin', '--', $pushUrl];
$this->process->execute($cmd, $ignoredOutput, $path);
}
}
@@ -526,10 +535,10 @@ protected function setPushUrl(string $path, string $url): void
protected function getCommitLogs(string $fromReference, string $toReference, string $path): string
{
$path = $this->normalizePath($path);
- $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"'.GitUtil::getNoShowSignatureFlag($this->process), ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
+ $command = array_merge(['git', 'log', $fromReference.'..'.$toReference, '--pretty=format:%h - %an: %s'], GitUtil::getNoShowSignatureFlags($this->process));
if (0 !== $this->process->execute($command, $output, $path)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+ throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
}
return $output;
@@ -542,7 +551,10 @@ protected function getCommitLogs(string $fromReference, string $toReference, str
protected function discardChanges(string $path): PromiseInterface
{
$path = $this->normalizePath($path);
- if (0 !== $this->process->execute('git clean -df && git reset --hard', $output, $path)) {
+ if (0 !== $this->process->execute(['git', 'clean', '-df'], $output, $path)) {
+ throw new \RuntimeException("Could not reset changes\n\n:".$output);
+ }
+ if (0 !== $this->process->execute(['git', 'reset', '--hard'], $output, $path)) {
throw new \RuntimeException("Could not reset changes\n\n:".$output);
}
@@ -558,7 +570,7 @@ protected function discardChanges(string $path): PromiseInterface
protected function stashChanges(string $path): PromiseInterface
{
$path = $this->normalizePath($path);
- if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
+ if (0 !== $this->process->execute(['git', 'stash', '--include-untracked'], $output, $path)) {
throw new \RuntimeException("Could not stash changes\n\n:".$output);
}
@@ -573,7 +585,7 @@ protected function stashChanges(string $path): PromiseInterface
protected function viewDiff(string $path): void
{
$path = $this->normalizePath($path);
- if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
+ if (0 !== $this->process->execute(['git', 'diff', 'HEAD'], $output, $path)) {
throw new \RuntimeException("Could not view diff\n\n:".$output);
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/GzipDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/GzipDownloader.php
index 9037f5226..010219822 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/GzipDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/GzipDownloader.php
@@ -31,7 +31,7 @@ protected function extract(PackageInterface $package, string $file, string $path
// Try to use gunzip on *nix
if (!Platform::isWindows()) {
- $command = 'gzip -cd -- ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
+ $command = ['sh', '-c', 'gzip -cd -- "$0" > "$1"', $file, $targetFilepath];
if (0 === $this->process->execute($command, $ignoredOutput)) {
return \React\Promise\resolve(null);
@@ -44,7 +44,7 @@ protected function extract(PackageInterface $package, string $file, string $path
return \React\Promise\resolve(null);
}
- $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
+ $processError = 'Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput();
throw new \RuntimeException($processError);
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/HgDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/HgDownloader.php
index b0cc9cd7d..4709ae35e 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/HgDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/HgDownloader.php
@@ -41,16 +41,15 @@ protected function doInstall(PackageInterface $package, string $path, string $ur
{
$hgUtils = new HgUtils($this->io, $this->config, $this->process);
- $cloneCommand = static function (string $url) use ($path): string {
- return sprintf('hg clone -- %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($path));
+ $cloneCommand = static function (string $url) use ($path): array {
+ return ['hg', 'clone', '--', $url, $path];
};
$hgUtils->runCommand($cloneCommand, $url, $path);
- $ref = ProcessExecutor::escape($package->getSourceReference());
- $command = sprintf('hg up -- %s', $ref);
+ $command = ['hg', 'up', '--', (string) $package->getSourceReference()];
if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+ throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
}
return \React\Promise\resolve(null);
@@ -70,10 +69,14 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
}
- $command = static function ($url) use ($ref): string {
- return sprintf('hg pull -- %s && hg up -- %s', ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
+ $command = static function ($url): array {
+ return ['hg', 'pull', '--', $url];
};
+ $hgUtils->runCommand($command, $url, $path);
+ $command = static function () use ($ref): array {
+ return ['hg', 'up', '--', $ref];
+ };
$hgUtils->runCommand($command, $url, $path);
return \React\Promise\resolve(null);
@@ -88,7 +91,7 @@ public function getLocalChanges(PackageInterface $package, string $path): ?strin
return null;
}
- $this->process->execute('hg st', $output, realpath($path));
+ $this->process->execute(['hg', 'st'], $output, realpath($path));
$output = trim($output);
@@ -100,10 +103,10 @@ public function getLocalChanges(PackageInterface $package, string $path): ?strin
*/
protected function getCommitLogs(string $fromReference, string $toReference, string $path): string
{
- $command = sprintf('hg log -r %s:%s --style compact', ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
+ $command = ['hg', 'log', '-r', $fromReference.':'.$toReference, '--style', 'compact'];
if (0 !== $this->process->execute($command, $output, realpath($path))) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
+ throw new \RuntimeException('Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput());
}
return $output;
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/PathDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/PathDownloader.php
index 791521bd6..f71ea2568 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/PathDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/PathDownloader.php
@@ -43,6 +43,9 @@ public function download(PackageInterface $package, string $path, ?PackageInterf
{
$path = Filesystem::trimTrailingSlash($path);
$url = $package->getDistUrl();
+ if (null === $url) {
+ throw new \RuntimeException('The package '.$package->getPrettyName().' has no dist url configured, cannot download.');
+ }
$realUrl = realpath($url);
if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
throw new \RuntimeException(sprintf(
@@ -79,7 +82,13 @@ public function install(PackageInterface $package, string $path, bool $output =
{
$path = Filesystem::trimTrailingSlash($path);
$url = $package->getDistUrl();
+ if (null === $url) {
+ throw new \RuntimeException('The package '.$package->getPrettyName().' has no dist url configured, cannot install.');
+ }
$realUrl = realpath($url);
+ if (false === $realUrl) {
+ throw new \RuntimeException('Failed to realpath '.$url);
+ }
if (realpath($path) === $realUrl) {
if ($output) {
@@ -111,16 +120,16 @@ public function install(PackageInterface $package, string $path, bool $output =
}
$this->filesystem->junction($realUrl, $path);
} else {
- $absolutePath = $path;
- if (!$this->filesystem->isAbsolutePath($absolutePath)) {
- $absolutePath = Platform::getCwd() . DIRECTORY_SEPARATOR . $path;
- }
- $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
$path = rtrim($path, "/");
if ($output) {
$this->io->writeError(sprintf('Symlinking from %s', $url), false);
}
- if ($transportOptions['relative']) {
+ if ($transportOptions['relative'] === true) {
+ $absolutePath = $path;
+ if (!$this->filesystem->isAbsolutePath($absolutePath)) {
+ $absolutePath = Platform::getCwd() . DIRECTORY_SEPARATOR . $path;
+ }
+ $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl, false, true);
$symfonyFilesystem->symlink($shortestPath.'/', $path);
} else {
$symfonyFilesystem->symlink($realUrl.'/', $path);
@@ -185,13 +194,18 @@ public function remove(PackageInterface $package, string $path, bool $output = t
return \React\Promise\resolve(null);
}
+ $url = $package->getDistUrl();
+ if (null === $url) {
+ throw new \RuntimeException('The package '.$package->getPrettyName().' has no dist url configured, cannot remove.');
+ }
+
// ensure that the source path (dist url) is not the same as the install path, which
// can happen when using custom installers, see https://github.com/composer/composer/pull/9116
// not using realpath here as we do not want to resolve the symlink to the original dist url
// it points to
$fs = new Filesystem;
$absPath = $fs->isAbsolutePath($path) ? $path : Platform::getCwd() . '/' . $path;
- $absDistUrl = $fs->isAbsolutePath($package->getDistUrl()) ? $package->getDistUrl() : Platform::getCwd() . '/' . $package->getDistUrl();
+ $absDistUrl = $fs->isAbsolutePath($url) ? $url : Platform::getCwd() . '/' . $url;
if ($fs->normalizePath($absPath) === $fs->normalizePath($absDistUrl)) {
if ($output) {
$this->io->writeError(" - " . UninstallOperation::format($package).", source is still present in $path");
@@ -210,11 +224,12 @@ public function getVcsReference(PackageInterface $package, string $path): ?strin
{
$path = Filesystem::trimTrailingSlash($path);
$parser = new VersionParser;
- $guesser = new VersionGuesser($this->config, $this->process, $parser);
+ $guesser = new VersionGuesser($this->config, $this->process, $parser, $this->io);
$dumper = new ArrayDumper;
$packageConfig = $dumper->dump($package);
- if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
+ $packageVersion = $guesser->guessVersion($packageConfig, $path);
+ if ($packageVersion !== null) {
return $packageVersion['commit'];
}
@@ -226,7 +241,14 @@ public function getVcsReference(PackageInterface $package, string $path): ?strin
*/
protected function getInstallOperationAppendix(PackageInterface $package, string $path): string
{
- $realUrl = realpath($package->getDistUrl());
+ $url = $package->getDistUrl();
+ if (null === $url) {
+ throw new \RuntimeException('The package '.$package->getPrettyName().' has no dist url configured, cannot install.');
+ }
+ $realUrl = realpath($url);
+ if (false === $realUrl) {
+ throw new \RuntimeException('Failed to realpath '.$url);
+ }
if (realpath($path) === $realUrl) {
return ': Source already present';
@@ -257,7 +279,7 @@ private function computeAllowedStrategies(array $transportOptions): array
$allowedStrategies = [self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR];
$mirrorPathRepos = Platform::getEnv('COMPOSER_MIRROR_PATH_REPOS');
- if ($mirrorPathRepos) {
+ if ((bool) $mirrorPathRepos) {
$currentStrategy = self::STRATEGY_MIRROR;
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/RarDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/RarDownloader.php
index a4142c655..04e16eaff 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/RarDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/RarDownloader.php
@@ -34,13 +34,13 @@ protected function extract(PackageInterface $package, string $file, string $path
// Try to use unrar on *nix
if (!Platform::isWindows()) {
- $command = 'unrar x -- ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
+ $command = ['sh', '-c', 'unrar x -- "$0" "$1" >/dev/null && chmod -R u+w "$1"', $file, $path];
if (0 === $this->process->execute($command, $ignoredOutput)) {
return \React\Promise\resolve(null);
}
- $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
+ $processError = 'Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput();
}
if (!class_exists('RarArchive')) {
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/SvnDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/SvnDownloader.php
index be180d63d..ca88ea839 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/SvnDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/SvnDownloader.php
@@ -59,7 +59,7 @@ protected function doInstall(PackageInterface $package, string $path, string $ur
}
$this->io->writeError(" Checking out ".$package->getSourceReference());
- $this->execute($package, $url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
+ $this->execute($package, $url, ['svn', 'co'], sprintf("%s/%s", $url, $ref), null, $path);
return \React\Promise\resolve(null);
}
@@ -77,13 +77,13 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
}
$util = new SvnUtil($url, $this->io, $this->config, $this->process);
- $flags = "";
+ $flags = [];
if (version_compare($util->binaryVersion(), '1.7.0', '>=')) {
- $flags .= ' --ignore-ancestry';
+ $flags[] = '--ignore-ancestry';
}
$this->io->writeError(" Checking out " . $ref);
- $this->execute($target, $url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
+ $this->execute($target, $url, array_merge(['svn', 'switch'], $flags), sprintf("%s/%s", $url, $ref), $path);
return \React\Promise\resolve(null);
}
@@ -97,7 +97,7 @@ public function getLocalChanges(PackageInterface $package, string $path): ?strin
return null;
}
- $this->process->execute('svn status --ignore-externals', $output, $path);
+ $this->process->execute(['svn', 'status', '--ignore-externals'], $output, $path);
return Preg::isMatch('{^ *[^X ] +}m', $output) ? $output : null;
}
@@ -107,13 +107,13 @@ public function getLocalChanges(PackageInterface $package, string $path): ?strin
* if necessary.
*
* @param string $baseUrl Base URL of the repository
- * @param string $command SVN command to run
+ * @param non-empty-list $command SVN command to run
* @param string $url SVN url
* @param string $cwd Working directory
* @param string $path Target for a checkout
* @throws \RuntimeException
*/
- protected function execute(PackageInterface $package, string $baseUrl, string $command, string $url, ?string $cwd = null, ?string $path = null): string
+ protected function execute(PackageInterface $package, string $baseUrl, array $command, string $url, ?string $cwd = null, ?string $path = null): string
{
$util = new SvnUtil($baseUrl, $this->io, $this->config, $this->process);
$util->setCacheCredentials($this->cacheCredentials);
@@ -194,10 +194,10 @@ protected function getCommitLogs(string $fromReference, string $toReference, str
{
if (Preg::isMatch('{@(\d+)$}', $fromReference) && Preg::isMatch('{@(\d+)$}', $toReference)) {
// retrieve the svn base url from the checkout folder
- $command = sprintf('svn info --non-interactive --xml -- %s', ProcessExecutor::escape($path));
+ $command = ['svn', 'info', '--non-interactive', '--xml', '--', $path];
if (0 !== $this->process->execute($command, $output, $path)) {
throw new \RuntimeException(
- 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
+ 'Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()
);
}
@@ -214,7 +214,7 @@ protected function getCommitLogs(string $fromReference, string $toReference, str
$fromRevision = Preg::replace('{.*@(\d+)$}', '$1', $fromReference);
$toRevision = Preg::replace('{.*@(\d+)$}', '$1', $toReference);
- $command = sprintf('svn log -r%s:%s --incremental', ProcessExecutor::escape($fromRevision), ProcessExecutor::escape($toRevision));
+ $command = ['svn', 'log', '-r', $fromRevision.':'.$toRevision, '--incremental'];
$util = new SvnUtil($baseUrl, $this->io, $this->config, $this->process);
$util->setCacheCredentials($this->cacheCredentials);
@@ -222,7 +222,7 @@ protected function getCommitLogs(string $fromReference, string $toReference, str
return $util->executeLocal($command, $path, null, $this->io->isVerbose());
} catch (\RuntimeException $e) {
throw new \RuntimeException(
- 'Failed to execute ' . $command . "\n\n".$e->getMessage()
+ 'Failed to execute ' . implode(' ', $command) . "\n\n".$e->getMessage()
);
}
}
@@ -235,7 +235,7 @@ protected function getCommitLogs(string $fromReference, string $toReference, str
*/
protected function discardChanges(string $path): PromiseInterface
{
- if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
+ if (0 !== $this->process->execute(['svn', 'revert', '-R', '.'], $output, $path)) {
throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/TransportException.php b/app/vendor/composer/composer/src/Composer/Downloader/TransportException.php
index 5ab5ca6f3..a30842e1e 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/TransportException.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/TransportException.php
@@ -26,7 +26,7 @@ class TransportException extends \RuntimeException
/** @var array */
protected $responseInfo = [];
- public function __construct(string $message = "", int $code = 400, \Throwable $previous = null)
+ public function __construct(string $message = "", int $code = 400, ?\Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/VcsDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/VcsDownloader.php
index a1c5979d5..626bcb5c5 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/VcsDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/VcsDownloader.php
@@ -241,7 +241,7 @@ public function remove(PackageInterface $package, string $path): PromiseInterfac
public function getVcsReference(PackageInterface $package, string $path): ?string
{
$parser = new VersionParser;
- $guesser = new VersionGuesser($this->config, $this->process, $parser);
+ $guesser = new VersionGuesser($this->config, $this->process, $parser, $this->io);
$dumper = new ArrayDumper;
$packageConfig = $dumper->dump($package);
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/XzDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/XzDownloader.php
index 8c44cd199..286d32cff 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/XzDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/XzDownloader.php
@@ -26,13 +26,13 @@ class XzDownloader extends ArchiveDownloader
{
protected function extract(PackageInterface $package, string $file, string $path): PromiseInterface
{
- $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
+ $command = ['tar', '-xJf', $file, '-C', $path];
if (0 === $this->process->execute($command, $ignoredOutput)) {
return \React\Promise\resolve(null);
}
- $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
+ $processError = 'Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput();
throw new \RuntimeException($processError);
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/ZipDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/ZipDownloader.php
index 9d0f35353..5c86579f8 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/ZipDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/ZipDownloader.php
@@ -27,7 +27,7 @@
*/
class ZipDownloader extends ArchiveDownloader
{
- /** @var array */
+ /** @var array> */
private static $unzipCommands;
/** @var bool */
private static $hasZipArchive;
@@ -35,7 +35,7 @@ class ZipDownloader extends ArchiveDownloader
private static $isWindows;
/** @var ZipArchive|null */
- private $zipArchiveObject; // @phpstan-ignore-line helper property that is set via reflection for testing purposes
+ private $zipArchiveObject; // @phpstan-ignore property.onlyRead (helper property that is set via reflection for testing purposes)
/**
* @inheritDoc
@@ -46,16 +46,16 @@ public function download(PackageInterface $package, string $path, ?PackageInterf
self::$unzipCommands = [];
$finder = new ExecutableFinder;
if (Platform::isWindows() && ($cmd = $finder->find('7z', null, ['C:\Program Files\7-Zip']))) {
- self::$unzipCommands[] = ['7z', ProcessExecutor::escape($cmd).' x -bb0 -y %s -o%s'];
+ self::$unzipCommands[] = ['7z', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%'];
}
if ($cmd = $finder->find('unzip')) {
- self::$unzipCommands[] = ['unzip', ProcessExecutor::escape($cmd).' -qq %s -d %s'];
+ self::$unzipCommands[] = ['unzip', $cmd, '-qq', '%file%', '-d', '%path%'];
}
if (!Platform::isWindows() && ($cmd = $finder->find('7z'))) { // 7z linux/macOS support is only used if unzip is not present
- self::$unzipCommands[] = ['7z', ProcessExecutor::escape($cmd).' x -bb0 -y %s -o%s'];
+ self::$unzipCommands[] = ['7z', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%'];
}
if (!Platform::isWindows() && ($cmd = $finder->find('7zz'))) { // 7zz linux/macOS support is only used if unzip is not present
- self::$unzipCommands[] = ['7zz', ProcessExecutor::escape($cmd).' x -bb0 -y %s -o%s'];
+ self::$unzipCommands[] = ['7zz', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%'];
}
}
@@ -114,24 +114,28 @@ private function extractWithSystemUnzip(PackageInterface $package, string $file,
// Force Exception throwing if the other alternative extraction method is not available
$isLastChance = !self::$hasZipArchive;
- if (!self::$unzipCommands) {
+ if (0 === \count(self::$unzipCommands)) {
// This was call as the favorite extract way, but is not available
// We switch to the alternative
return $this->extractWithZipArchive($package, $file, $path);
}
$commandSpec = reset(self::$unzipCommands);
- $command = sprintf($commandSpec[1], ProcessExecutor::escape($file), ProcessExecutor::escape($path));
- // normalize separators to backslashes to avoid problems with 7-zip on windows
- // see https://github.com/composer/composer/issues/10058
- if (Platform::isWindows()) {
- $command = sprintf($commandSpec[1], ProcessExecutor::escape(strtr($file, '/', '\\')), ProcessExecutor::escape(strtr($path, '/', '\\')));
- }
-
$executable = $commandSpec[0];
+ $command = array_slice($commandSpec, 1);
+ $map = [
+ // normalize separators to backslashes to avoid problems with 7-zip on windows
+ // see https://github.com/composer/composer/issues/10058
+ '%file%' => strtr($file, '/', DIRECTORY_SEPARATOR),
+ '%path%' => strtr($path, '/', DIRECTORY_SEPARATOR),
+ ];
+ $command = array_map(static function ($value) use ($map) {
+ return strtr($value, $map);
+ }, $command);
+
if (!$warned7ZipLinux && !Platform::isWindows() && in_array($executable, ['7z', '7zz'], true)) {
$warned7ZipLinux = true;
- if (0 === $this->process->execute($executable, $output)) {
+ if (0 === $this->process->execute([$commandSpec[1]], $output)) {
if (Preg::isMatchStrictGroups('{^\s*7-Zip(?: \[64\])? ([0-9.]+)}', $output, $match) && version_compare($match[1], '21.01', '<')) {
$this->io->writeError(' Unzipping using '.$executable.' '.$match[1].' may result in incorrect file permissions. Install '.$executable.' 21.01+ or unzip to ensure you get correct permissions.');
}
@@ -144,6 +148,10 @@ private function extractWithSystemUnzip(PackageInterface $package, string $file,
throw $processError;
}
+ if (str_contains($processError->getMessage(), 'zip bomb')) {
+ throw $processError;
+ }
+
if (!is_file($file)) {
$io->writeError(' '.$processError->getMessage().'');
$io->writeError(' This most likely is due to a custom installer plugin not handling the returned Promise from the downloader');
@@ -182,7 +190,7 @@ private function extractWithSystemUnzip(PackageInterface $package, string $file,
$output = $process->getErrorOutput();
$output = str_replace(', '.$file.'.zip or '.$file.'.ZIP', '', $output);
- return $tryFallback(new \RuntimeException('Failed to extract '.$package->getName().': ('.$process->getExitCode().') '.$command."\n\n".$output));
+ return $tryFallback(new \RuntimeException('Failed to extract '.$package->getName().': ('.$process->getExitCode().') '.implode(' ', $command)."\n\n".$output));
}
});
} catch (\Throwable $e) {
@@ -208,7 +216,32 @@ private function extractWithZipArchive(PackageInterface $package, string $file,
} else {
$retval = $zipArchive->open($file);
}
+
if (true === $retval) {
+ $totalSize = 0;
+ $archiveSize = filesize($file);
+ $totalFiles = $zipArchive->count();
+ if ($totalFiles > 0) {
+ $inspectAll = false;
+ $filesToInspect = min($totalFiles, 5);
+ for ($i = 0; $i < $filesToInspect; $i++) {
+ $stat = $zipArchive->statIndex($inspectAll ? $i : random_int(0, $totalFiles - 1));
+ if ($stat === false) {
+ continue;
+ }
+ $totalSize += $stat['size'];
+ if (!$inspectAll && $stat['size'] > $stat['comp_size'] * 200) {
+ $totalSize = 0;
+ $inspectAll = true;
+ $i = -1;
+ $filesToInspect = $totalFiles;
+ }
+ }
+ if ($archiveSize !== false && $totalSize > $archiveSize * 100 && $totalSize > 50*1024*1024) {
+ throw new \RuntimeException('Invalid zip file for "'.$package->getName().'" with compression ratio >99% (possible zip bomb)');
+ }
+ }
+
$extractResult = $zipArchive->extractTo($path);
if (true === $extractResult) {
@@ -217,12 +250,12 @@ private function extractWithZipArchive(PackageInterface $package, string $file,
return \React\Promise\resolve(null);
}
- $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
+ $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file for \"{$package->getName()}\", it is either corrupted or using an invalid format.\n"));
} else {
$processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
}
} catch (\ErrorException $e) {
- $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
+ $processError = new \RuntimeException('The archive for "'.$package->getName().'" may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
} catch (\Throwable $e) {
$processError = $e;
}
diff --git a/app/vendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php b/app/vendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php
index cab856252..6f34a6f64 100644
--- a/app/vendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php
+++ b/app/vendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php
@@ -67,6 +67,8 @@ class EventDispatcher
protected $runScripts = true;
/** @var list */
private $eventStack;
+ /** @var list */
+ private $skipScripts;
/**
* Constructor.
@@ -81,6 +83,12 @@ public function __construct(PartialComposer $composer, IOInterface $io, ?Process
$this->io = $io;
$this->process = $process ?? new ProcessExecutor($io);
$this->eventStack = [];
+ $this->skipScripts = array_values(array_filter(
+ array_map('trim', explode(',', (string) Platform::getEnv('COMPOSER_SKIP_SCRIPTS'))),
+ function ($val) {
+ return $val !== '';
+ }
+ ));
}
/**
@@ -90,7 +98,7 @@ public function __construct(PartialComposer $composer, IOInterface $io, ?Process
*/
public function setRunScripts(bool $runScripts = true): self
{
- $this->runScripts = (bool) $runScripts;
+ $this->runScripts = $runScripts;
return $this;
}
@@ -202,7 +210,12 @@ protected function doDispatch(Event $event)
$return = 0;
$this->ensureBinDirIsInPath();
- $formattedEventNameWithArgs = $event->getName() . ($event->getArguments() !== [] ? ' (' . implode(', ', $event->getArguments()) . ')' : '');
+ $additionalArgs = $event->getArguments();
+ if (is_string($callable) && str_contains($callable, '@no_additional_args')) {
+ $callable = Preg::replace('{ ?@no_additional_args}', '', $callable);
+ $additionalArgs = [];
+ }
+ $formattedEventNameWithArgs = $event->getName() . ($additionalArgs !== [] ? ' (' . implode(', ', $additionalArgs) . ')' : '');
if (!is_string($callable)) {
if (!is_callable($callable)) {
$className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
@@ -220,7 +233,12 @@ protected function doDispatch(Event $event)
$scriptName = $script[0];
unset($script[0]);
- $args = array_merge($script, $event->getArguments());
+ $index = array_search('@additional_args', $script, true);
+ if ($index !== false) {
+ $args = array_splice($script, $index, 0, $additionalArgs);
+ } else {
+ $args = array_merge($script, $additionalArgs);
+ }
$flags = $event->getFlags();
if (isset($flags['script-alias-input'])) {
$argsString = implode(' ', array_map(static function ($arg) { return ProcessExecutor::escape($arg); }, $script));
@@ -291,15 +309,20 @@ protected function doDispatch(Event $event)
}
$app->setAutoExit(false);
$cmd = new $className($event->getName());
- $app->add($cmd);
+ if (method_exists($app, 'addCommand')) {
+ $app->addCommand($cmd);
+ } else {
+ // Compatibility layer for symfony/console <7.4
+ $app->add($cmd);
+ }
$app->setDefaultCommand((string) $cmd->getName(), true);
try {
- $args = implode(' ', array_map(static function ($arg) { return ProcessExecutor::escape($arg); }, $event->getArguments()));
+ $args = implode(' ', array_map(static function ($arg) { return ProcessExecutor::escape($arg); }, $additionalArgs));
// reusing the output from $this->io is mostly needed for tests, but generally speaking
// it does not hurt to keep the same stream as the current Application
if ($this->io instanceof ConsoleIO) {
$reflProp = new \ReflectionProperty($this->io, 'output');
- if (PHP_VERSION_ID < 80100) {
+ if (\PHP_VERSION_ID < 80100) {
$reflProp->setAccessible(true);
}
$output = $reflProp->getValue($this->io);
@@ -313,24 +336,32 @@ protected function doDispatch(Event $event)
throw $e;
}
} else {
- $args = implode(' ', array_map(['Composer\Util\ProcessExecutor', 'escape'], $event->getArguments()));
+ $args = implode(' ', array_map(['Composer\Util\ProcessExecutor', 'escape'], $additionalArgs));
// @putenv does not receive arguments
if (strpos($callable, '@putenv ') === 0) {
$exec = $callable;
} else {
- $exec = $callable . ($args === '' ? '' : ' '.$args);
+ if (str_contains($callable, '@additional_args')) {
+ $exec = str_replace('@additional_args', $args, $callable);
+ } else {
+ $exec = $callable . ($args === '' ? '' : ' '.$args);
+ }
}
if ($this->io->isVerbose()) {
$this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
- } elseif ($event->getName() !== '__exec_command') {
+ } elseif (
// do not output the command being run when using `composer exec` as it is fairly obvious the user is running it
+ $event->getName() !== '__exec_command'
+ // do not output the command being run when using `composer ` as it is also fairly obvious the user is running it
+ && ($event->getFlags()['script-alias-input'] ?? null) === null
+ ) {
$this->io->writeError(sprintf('> %s', $exec));
}
$possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
- if ($possibleLocalBinaries) {
+ if (count($possibleLocalBinaries) > 0) {
foreach ($possibleLocalBinaries as $localExec) {
if (Preg::isMatch('{\b'.preg_quote($callable).'$}', $localExec)) {
$caller = BinaryInstaller::determineBinaryCaller($localExec);
@@ -354,7 +385,7 @@ protected function doDispatch(Event $event)
$pathAndArgs = substr($exec, 5);
if (Platform::isWindows()) {
$pathAndArgs = Preg::replaceCallback('{^\S+}', static function ($path) {
- return str_replace('/', '\\', (string) $path[0]);
+ return str_replace('/', '\\', $path[0]);
}, $pathAndArgs);
}
// match somename (not in quote, and not a qualified path) and if it is not a valid path from CWD then try to find it
@@ -384,8 +415,6 @@ protected function doDispatch(Event $event)
if (Platform::isWindows()) {
$exec = Preg::replaceCallback('{^\S+}', static function ($path) {
- assert(is_string($path[0]));
-
return str_replace('/', '\\', $path[0]);
}, $exec);
}
@@ -455,7 +484,7 @@ protected function getPhpExecCommand(): string
throw new \RuntimeException('Failed to locate PHP binary to execute '.$phpPath);
}
$phpArgs = $finder->findArguments();
- $phpArgs = $phpArgs ? ' ' . implode(' ', $phpArgs) : '';
+ $phpArgs = \count($phpArgs) > 0 ? ' ' . implode(' ', $phpArgs) : '';
$allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
$disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
$memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
@@ -572,6 +601,12 @@ protected function getScriptListeners(Event $event): array
return [];
}
+ if (in_array($event->getName(), $this->skipScripts, true)) {
+ $this->io->writeError('Skipped script listeners for '.$event->getName().' because of COMPOSER_SKIP_SCRIPTS', true, IOInterface::VERBOSE);
+
+ return [];
+ }
+
assert($this->composer instanceof Composer, new \LogicException('This should only be reached with a fully loaded Composer'));
if ($this->loader) {
diff --git a/app/vendor/composer/composer/src/Composer/Factory.php b/app/vendor/composer/composer/src/Composer/Factory.php
index 0d455b7e3..539989904 100644
--- a/app/vendor/composer/composer/src/Composer/Factory.php
+++ b/app/vendor/composer/composer/src/Composer/Factory.php
@@ -216,29 +216,26 @@ public static function createConfig(?IOInterface $io = null, ?string $cwd = null
}
$config->setAuthConfigSource(new JsonConfigSource($file, true));
- // load COMPOSER_AUTH environment variable if set
- if ($composerAuthEnv = Platform::getEnv('COMPOSER_AUTH')) {
- $authData = json_decode($composerAuthEnv);
- if (null === $authData) {
- throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
- } else {
- if ($io instanceof IOInterface) {
- $io->writeError('Loading auth config from COMPOSER_AUTH', true, IOInterface::DEBUG);
- }
- self::validateJsonSchema($io, $authData, JsonFile::AUTH_SCHEMA, 'COMPOSER_AUTH');
- $authData = json_decode($composerAuthEnv, true);
- if (null !== $authData) {
- $config->merge(['config' => $authData], 'COMPOSER_AUTH');
- }
- }
- }
+ self::loadComposerAuthEnv($config, $io);
return $config;
}
public static function getComposerFile(): string
{
- return trim((string) Platform::getEnv('COMPOSER')) ?: './composer.json';
+ $env = Platform::getEnv('COMPOSER');
+ if (is_string($env)) {
+ $env = trim($env);
+ if ('' !== $env) {
+ if (is_dir($env)) {
+ throw new \RuntimeException('The COMPOSER environment variable is set to '.$env.' which is a directory, this variable should point to a composer.json or be left unset.');
+ }
+
+ return $env;
+ }
+ }
+
+ return './composer.json';
}
public static function getLockFile(string $composerFile): string
@@ -327,7 +324,9 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
// Load config and override with local config/auth config
$config = static::createConfig($io, $cwd);
+ $isGlobal = $localConfigSource !== Config::SOURCE_UNKNOWN && realpath($config->get('home')) === realpath(dirname($localConfigSource));
$config->merge($localConfig, $localConfigSource);
+
if (isset($composerFile)) {
$io->writeError('Loading config file ' . $composerFile .' ('.realpath($composerFile).')', true, IOInterface::DEBUG);
$config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
@@ -341,11 +340,17 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
}
}
+ // make sure we load the auth env again over the local auth.json + composer.json config
+ self::loadComposerAuthEnv($config, $io);
+
$vendorDir = $config->get('vendor-dir');
// initialize composer
$composer = $fullLoad ? new Composer() : new PartialComposer();
$composer->setConfig($config);
+ if ($isGlobal) {
+ $composer->setGlobal();
+ }
if ($fullLoad) {
// load auth configs into the IO instance
@@ -384,7 +389,7 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
// load package
$parser = new VersionParser;
- $guesser = new VersionGuesser($config, $process, $parser);
+ $guesser = new VersionGuesser($config, $process, $parser, $io);
$loader = $this->loadRootPackage($rm, $config, $parser, $guesser, $io);
$package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
$composer->setPackage($package);
@@ -429,14 +434,14 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
if ($composer instanceof Composer) {
$globalComposer = null;
- if (realpath($config->get('home')) !== $cwd) {
+ if (!$composer->isGlobal()) {
$globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins, $disableScripts);
}
$pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
$composer->setPluginManager($pm);
- if (realpath($config->get('home')) === $cwd) {
+ if ($composer->isGlobal()) {
$pm->setRunningInGlobalDir(true);
}
@@ -678,6 +683,28 @@ public static function createHttpDownloader(IOInterface $io, Config $config, arr
return $httpDownloader;
}
+ private static function loadComposerAuthEnv(Config $config, ?IOInterface $io): void
+ {
+ $composerAuthEnv = Platform::getEnv('COMPOSER_AUTH');
+ if (false === $composerAuthEnv || '' === $composerAuthEnv) {
+ return;
+ }
+
+ $authData = json_decode($composerAuthEnv);
+ if (null === $authData) {
+ throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
+ }
+
+ if ($io instanceof IOInterface) {
+ $io->writeError('Loading auth config from COMPOSER_AUTH', true, IOInterface::DEBUG);
+ }
+ self::validateJsonSchema($io, $authData, JsonFile::AUTH_SCHEMA, 'COMPOSER_AUTH');
+ $authData = json_decode($composerAuthEnv, true);
+ if (null !== $authData) {
+ $config->merge(['config' => $authData], 'COMPOSER_AUTH');
+ }
+ }
+
private static function useXdg(): bool
{
foreach (array_keys($_SERVER) as $key) {
diff --git a/app/vendor/composer/composer/src/Composer/IO/BaseIO.php b/app/vendor/composer/composer/src/Composer/IO/BaseIO.php
index c4d40ba01..55ac16604 100644
--- a/app/vendor/composer/composer/src/Composer/IO/BaseIO.php
+++ b/app/vendor/composer/composer/src/Composer/IO/BaseIO.php
@@ -176,46 +176,74 @@ public function loadConfiguration(Config $config)
ProcessExecutor::setTimeout($config->get('process-timeout'));
}
+ /**
+ * @param string|\Stringable $message
+ */
public function emergency($message, array $context = []): void
{
$this->log(LogLevel::EMERGENCY, $message, $context);
}
+ /**
+ * @param string|\Stringable $message
+ */
public function alert($message, array $context = []): void
{
$this->log(LogLevel::ALERT, $message, $context);
}
+ /**
+ * @param string|\Stringable $message
+ */
public function critical($message, array $context = []): void
{
$this->log(LogLevel::CRITICAL, $message, $context);
}
+ /**
+ * @param string|\Stringable $message
+ */
public function error($message, array $context = []): void
{
$this->log(LogLevel::ERROR, $message, $context);
}
+ /**
+ * @param string|\Stringable $message
+ */
public function warning($message, array $context = []): void
{
$this->log(LogLevel::WARNING, $message, $context);
}
+ /**
+ * @param string|\Stringable $message
+ */
public function notice($message, array $context = []): void
{
$this->log(LogLevel::NOTICE, $message, $context);
}
+ /**
+ * @param string|\Stringable $message
+ */
public function info($message, array $context = []): void
{
$this->log(LogLevel::INFO, $message, $context);
}
+ /**
+ * @param string|\Stringable $message
+ */
public function debug($message, array $context = []): void
{
$this->log(LogLevel::DEBUG, $message, $context);
}
+ /**
+ * @param mixed|LogLevel::* $level
+ * @param string|\Stringable $message
+ */
public function log($level, $message, array $context = []): void
{
$message = (string) $message;
diff --git a/app/vendor/composer/composer/src/Composer/IO/BufferIO.php b/app/vendor/composer/composer/src/Composer/IO/BufferIO.php
index 0404287a0..6cf962b84 100644
--- a/app/vendor/composer/composer/src/Composer/IO/BufferIO.php
+++ b/app/vendor/composer/composer/src/Composer/IO/BufferIO.php
@@ -14,6 +14,8 @@
use Composer\Pcre\Preg;
use Symfony\Component\Console\Helper\QuestionHelper;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\Console\Input\StreamableInputInterface;
@@ -25,17 +27,16 @@
*/
class BufferIO extends ConsoleIO
{
- /** @var StringInput */
- protected $input;
- /** @var StreamOutput */
- protected $output;
-
public function __construct(string $input = '', int $verbosity = StreamOutput::VERBOSITY_NORMAL, ?OutputFormatterInterface $formatter = null)
{
$input = new StringInput($input);
$input->setInteractive(false);
- $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
+ $stream = fopen('php://memory', 'rw');
+ if ($stream === false) {
+ throw new \RuntimeException('Unable to open memory output stream');
+ }
+ $output = new StreamOutput($stream, $verbosity, $formatter !== null ? $formatter->isDecorated() : false, $formatter);
parent::__construct($input, $output, new HelperSet([
new QuestionHelper(),
@@ -47,13 +48,12 @@ public function __construct(string $input = '', int $verbosity = StreamOutput::V
*/
public function getOutput(): string
{
+ assert($this->output instanceof StreamOutput);
fseek($this->output->getStream(), 0);
- $output = stream_get_contents($this->output->getStream());
+ $output = (string) stream_get_contents($this->output->getStream());
$output = Preg::replaceCallback("{(?<=^|\n|\x08)(.+?)(\x08+)}", static function ($matches): string {
- assert(is_string($matches[1]));
- assert(is_string($matches[2]));
$pre = strip_tags($matches[1]);
if (strlen($pre) === strlen($matches[2])) {
@@ -85,11 +85,14 @@ public function setUserInputs(array $inputs): void
/**
* @param string[] $inputs
*
- * @return false|resource stream
+ * @return resource stream
*/
private function createStream(array $inputs)
{
$stream = fopen('php://memory', 'r+');
+ if ($stream === false) {
+ throw new \RuntimeException('Unable to open memory output stream');
+ }
foreach ($inputs as $input) {
fwrite($stream, $input.PHP_EOL);
diff --git a/app/vendor/composer/composer/src/Composer/InstalledVersions.php b/app/vendor/composer/composer/src/Composer/InstalledVersions.php
index 51e734a77..2052022fd 100644
--- a/app/vendor/composer/composer/src/Composer/InstalledVersions.php
+++ b/app/vendor/composer/composer/src/Composer/InstalledVersions.php
@@ -26,12 +26,23 @@
*/
class InstalledVersions
{
+ /**
+ * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
+ * @internal
+ */
+ private static $selfDir = null;
+
/**
* @var mixed[]|null
* @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}|array{}|null
*/
private static $installed;
+ /**
+ * @var bool
+ */
+ private static $installedIsLocalDir;
+
/**
* @var bool|null
*/
@@ -309,6 +320,24 @@ public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
+
+ // when using reload, we disable the duplicate protection to ensure that self::$installed data is
+ // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
+ // so we have to assume it does not, and that may result in duplicate data being returned when listing
+ // all installed packages for example
+ self::$installedIsLocalDir = false;
+ }
+
+ /**
+ * @return string
+ */
+ private static function getSelfDir()
+ {
+ if (self::$selfDir === null) {
+ self::$selfDir = strtr(__DIR__, '\\', '/');
+ }
+
+ return self::$selfDir;
}
/**
@@ -322,19 +351,27 @@ private static function getInstalled()
}
$installed = array();
+ $copiedLocalDir = false;
if (self::$canGetVendors) {
+ $selfDir = self::getSelfDir();
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+ $vendorDir = strtr($vendorDir, '\\', '/');
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
/** @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} $required */
$required = require $vendorDir.'/composer/installed.php';
- $installed[] = self::$installedByVendor[$vendorDir] = $required;
- if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
- self::$installed = $installed[count($installed) - 1];
+ self::$installedByVendor[$vendorDir] = $required;
+ $installed[] = $required;
+ if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
+ self::$installed = $required;
+ self::$installedIsLocalDir = true;
}
}
+ if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
+ $copiedLocalDir = true;
+ }
}
}
@@ -350,7 +387,7 @@ private static function getInstalled()
}
}
- if (self::$installed !== array()) {
+ if (self::$installed !== array() && !$copiedLocalDir) {
$installed[] = self::$installed;
}
diff --git a/app/vendor/composer/composer/src/Composer/Installer.php b/app/vendor/composer/composer/src/Composer/Installer.php
index 5f07b0e17..2502a7d02 100644
--- a/app/vendor/composer/composer/src/Composer/Installer.php
+++ b/app/vendor/composer/composer/src/Composer/Installer.php
@@ -538,10 +538,7 @@ protected function doUpdate(InstalledRepositoryInterface $localRepo, bool $doIns
return $exitCode;
}
- // exists as of composer/semver 3.3.0
- if (method_exists('Composer\Semver\CompilingMatcher', 'clear')) { // @phpstan-ignore-line
- \Composer\Semver\CompilingMatcher::clear();
- }
+ \Composer\Semver\CompilingMatcher::clear();
// write lock
$platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
@@ -745,16 +742,31 @@ protected function doInstall(InstalledRepositoryInterface $localRepo, bool $alre
if ($missingRequirementInfo !== []) {
$this->io->writeError($missingRequirementInfo);
- return self::ERROR_LOCK_FILE_INVALID;
+ if (!$this->config->get('allow-missing-requirements')) {
+ return self::ERROR_LOCK_FILE_INVALID;
+ }
}
foreach ($lockedRepository->getPackages() as $package) {
$request->fixLockedPackage($package);
}
+ $rootRequires = $this->package->getRequires();
+ if ($this->devMode) {
+ $rootRequires = array_merge($rootRequires, $this->package->getDevRequires());
+ }
+ foreach ($rootRequires as $link) {
+ if (PlatformRepository::isPlatformPackage($link->getTarget())) {
+ $request->requireName($link->getTarget(), $link->getConstraint());
+ }
+ }
+
foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
- $request->requireName($link->getTarget(), $link->getConstraint());
+ if (!isset($rootRequires[$link->getTarget()])) {
+ $request->requireName($link->getTarget(), $link->getConstraint());
+ }
}
+ unset($rootRequires, $link);
$pool = $repositorySet->createPool($request, $this->io, $this->eventDispatcher, null, $this->ignoredTypes, $this->allowedTypes);
@@ -900,7 +912,7 @@ private function createRepositorySet(bool $forUpdate, PlatformRepository $platfo
$this->fixedRootPackage->setRequires([]);
$this->fixedRootPackage->setDevRequires([]);
- $stabilityFlags[$this->package->getName()] = BasePackage::$stabilities[VersionParser::parseStability($this->package->getVersion())];
+ $stabilityFlags[$this->package->getName()] = BasePackage::STABILITIES[VersionParser::parseStability($this->package->getVersion())];
$repositorySet = new RepositorySet($minimumStability, $stabilityFlags, $rootAliases, $this->package->getReferences(), $rootRequires, $this->temporaryConstraints);
$repositorySet->addRepository(new RootPackageRepository($this->fixedRootPackage));
@@ -1163,7 +1175,7 @@ public function setTemporaryConstraints(array $constraints): self
*/
public function setDryRun(bool $dryRun = true): self
{
- $this->dryRun = (bool) $dryRun;
+ $this->dryRun = $dryRun;
return $this;
}
@@ -1195,7 +1207,7 @@ public function setDownloadOnly(bool $downloadOnly = true): self
*/
public function setPreferSource(bool $preferSource = true): self
{
- $this->preferSource = (bool) $preferSource;
+ $this->preferSource = $preferSource;
return $this;
}
@@ -1207,7 +1219,7 @@ public function setPreferSource(bool $preferSource = true): self
*/
public function setPreferDist(bool $preferDist = true): self
{
- $this->preferDist = (bool) $preferDist;
+ $this->preferDist = $preferDist;
return $this;
}
@@ -1219,7 +1231,7 @@ public function setPreferDist(bool $preferDist = true): self
*/
public function setOptimizeAutoloader(bool $optimizeAutoloader): self
{
- $this->optimizeAutoloader = (bool) $optimizeAutoloader;
+ $this->optimizeAutoloader = $optimizeAutoloader;
if (!$this->optimizeAutoloader) {
// Force classMapAuthoritative off when not optimizing the
// autoloader
@@ -1237,7 +1249,7 @@ public function setOptimizeAutoloader(bool $optimizeAutoloader): self
*/
public function setClassMapAuthoritative(bool $classMapAuthoritative): self
{
- $this->classMapAuthoritative = (bool) $classMapAuthoritative;
+ $this->classMapAuthoritative = $classMapAuthoritative;
if ($this->classMapAuthoritative) {
// Force optimizeAutoloader when classmap is authoritative
$this->setOptimizeAutoloader(true);
@@ -1266,7 +1278,7 @@ public function setApcuAutoloader(bool $apcuAutoloader, ?string $apcuAutoloaderP
*/
public function setUpdate(bool $update): self
{
- $this->update = (bool) $update;
+ $this->update = $update;
return $this;
}
@@ -1278,7 +1290,7 @@ public function setUpdate(bool $update): self
*/
public function setInstall(bool $install): self
{
- $this->install = (bool) $install;
+ $this->install = $install;
return $this;
}
@@ -1290,7 +1302,7 @@ public function setInstall(bool $install): self
*/
public function setDevMode(bool $devMode = true): self
{
- $this->devMode = (bool) $devMode;
+ $this->devMode = $devMode;
return $this;
}
@@ -1304,7 +1316,7 @@ public function setDevMode(bool $devMode = true): self
*/
public function setDumpAutoloader(bool $dumpAutoloader = true): self
{
- $this->dumpAutoloader = (bool) $dumpAutoloader;
+ $this->dumpAutoloader = $dumpAutoloader;
return $this;
}
@@ -1319,7 +1331,7 @@ public function setDumpAutoloader(bool $dumpAutoloader = true): self
*/
public function setRunScripts(bool $runScripts = true): self
{
- $this->runScripts = (bool) $runScripts;
+ $this->runScripts = $runScripts;
return $this;
}
@@ -1343,7 +1355,7 @@ public function setConfig(Config $config): self
*/
public function setVerbose(bool $verbose = true): self
{
- $this->verbose = (bool) $verbose;
+ $this->verbose = $verbose;
return $this;
}
diff --git a/app/vendor/composer/composer/src/Composer/Installer/BinaryInstaller.php b/app/vendor/composer/composer/src/Composer/Installer/BinaryInstaller.php
index 9e3123ff8..921132552 100644
--- a/app/vendor/composer/composer/src/Composer/Installer/BinaryInstaller.php
+++ b/app/vendor/composer/composer/src/Composer/Installer/BinaryInstaller.php
@@ -213,7 +213,7 @@ protected function generateUnixyProxyCode(string $bin, string $link): string
$binDir = ProcessExecutor::escape(dirname($binPath));
$binFile = basename($binPath);
- $binContents = file_get_contents($bin);
+ $binContents = (string) file_get_contents($bin, false, null, 0, 500);
// For php files, we generate a PHP proxy instead of a shell one,
// which allows calling the proxy with a custom php process
if (Preg::isMatch('{^(#!.*\r?\n)?[\r\n\t ]*<\?php}', $binContents, $match)) {
@@ -224,7 +224,7 @@ protected function generateUnixyProxyCode(string $bin, string $link): string
$globalsCode = '$GLOBALS[\'_composer_bin_dir\'] = __DIR__;'."\n";
$phpunitHack1 = $phpunitHack2 = '';
// Don't expose autoload path when vendor dir was not set in custom installers
- if ($this->vendorDir) {
+ if ($this->vendorDir !== null) {
// ensure comparisons work accurately if the CWD is a symlink, as $link is realpath'd already
$vendorDirReal = realpath($this->vendorDir);
if ($vendorDirReal === false) {
@@ -242,7 +242,7 @@ protected function generateUnixyProxyCode(string $bin, string $link): string
$data = str_replace(\'__DIR__\', var_export(dirname($this->realpath), true), $data);
$data = str_replace(\'__FILE__\', var_export($this->realpath, true), $data);';
}
- if (trim((string) $match[0]) !== ' */
+ /** @var list */
private $installers = [];
/** @var array */
private $cache = [];
@@ -180,7 +180,7 @@ public function ensureBinariesPresence(PackageInterface $package): void
*/
public function execute(InstalledRepositoryInterface $repo, array $operations, bool $devMode = true, bool $runScripts = true, bool $downloadOnly = false): void
{
- /** @var array> */
+ /** @var array> $cleanupPromises */
$cleanupPromises = [];
$signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) use (&$cleanupPromises) {
@@ -197,25 +197,28 @@ public function execute(InstalledRepositoryInterface $repo, array $operations, b
foreach ($operations as $index => $operation) {
if ($operation instanceof UpdateOperation || $operation instanceof InstallOperation) {
$package = $operation instanceof UpdateOperation ? $operation->getTargetPackage() : $operation->getPackage();
- if ($package->getType() === 'composer-plugin' && ($extra = $package->getExtra()) && isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === true) {
- if ($batch) {
- $batches[] = $batch;
+ if ($package->getType() === 'composer-plugin') {
+ $extra = $package->getExtra();
+ if (isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === true) {
+ if (count($batch) > 0) {
+ $batches[] = $batch;
+ }
+ $batches[] = [$index => $operation];
+ $batch = [];
+
+ continue;
}
- $batches[] = [$index => $operation];
- $batch = [];
-
- continue;
}
}
$batch[$index] = $operation;
}
- if ($batch) {
+ if (count($batch) > 0) {
$batches[] = $batch;
}
- foreach ($batches as $batch) {
- $this->downloadAndExecuteBatch($repo, $batch, $cleanupPromises, $devMode, $runScripts, $downloadOnly, $operations);
+ foreach ($batches as $batchToExecute) {
+ $this->downloadAndExecuteBatch($repo, $batchToExecute, $cleanupPromises, $devMode, $runScripts, $downloadOnly, $operations);
}
} catch (\Exception $e) {
$this->runCleanup($cleanupPromises);
@@ -248,7 +251,7 @@ private function downloadAndExecuteBatch(InstalledRepositoryInterface $repo, arr
$opType = $operation->getOperationType();
// ignoring alias ops as they don't need to execute anything at this stage
- if (!in_array($opType, ['update', 'install', 'uninstall'])) {
+ if (!in_array($opType, ['update', 'install', 'uninstall'], true)) {
continue;
}
@@ -266,7 +269,7 @@ private function downloadAndExecuteBatch(InstalledRepositoryInterface $repo, arr
$cleanupPromises[$index] = static function () use ($opType, $installer, $package, $initialPackage): ?PromiseInterface {
// avoid calling cleanup if the download was not even initialized for a package
// as without installation source configured nothing will work
- if (!$package->getInstallationSource()) {
+ if (null === $package->getInstallationSource()) {
return \React\Promise\resolve(null);
}
@@ -282,7 +285,7 @@ private function downloadAndExecuteBatch(InstalledRepositoryInterface $repo, arr
}
// execute all downloads first
- if (count($promises)) {
+ if (count($promises) > 0) {
$this->waitOnPromises($promises);
}
@@ -299,7 +302,7 @@ private function downloadAndExecuteBatch(InstalledRepositoryInterface $repo, arr
if ($operation instanceof InstallOperation || $operation instanceof UpdateOperation) {
$package = $operation instanceof UpdateOperation ? $operation->getTargetPackage() : $operation->getPackage();
if ($package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer') {
- if ($batch) {
+ if (count($batch) > 0) {
$batches[] = $batch;
}
$batches[] = [$index => $operation];
@@ -311,12 +314,12 @@ private function downloadAndExecuteBatch(InstalledRepositoryInterface $repo, arr
$batch[$index] = $operation;
}
- if ($batch) {
+ if (count($batch) > 0) {
$batches[] = $batch;
}
- foreach ($batches as $batch) {
- $this->executeBatch($repo, $batch, $cleanupPromises, $devMode, $runScripts, $allOperations);
+ foreach ($batches as $batchToExecute) {
+ $this->executeBatch($repo, $batchToExecute, $cleanupPromises, $devMode, $runScripts, $allOperations);
}
}
@@ -334,7 +337,7 @@ private function executeBatch(InstalledRepositoryInterface $repo, array $operati
$opType = $operation->getOperationType();
// ignoring alias ops as they don't need to execute anything
- if (!in_array($opType, ['update', 'install', 'uninstall'])) {
+ if (!in_array($opType, ['update', 'install', 'uninstall'], true)) {
// output alias ops in debug verbosity as they have no output otherwise
if ($this->io->isDebug()) {
$this->io->writeError(' - ' . $operation->show(false));
@@ -360,9 +363,9 @@ private function executeBatch(InstalledRepositoryInterface $repo, array $operati
'install' => PackageEvents::PRE_PACKAGE_INSTALL,
'update' => PackageEvents::PRE_PACKAGE_UPDATE,
'uninstall' => PackageEvents::PRE_PACKAGE_UNINSTALL,
- ][$opType] ?? null;
+ ][$opType];
- if (null !== $eventName && $runScripts && $this->eventDispatcher) {
+ if ($runScripts && $this->eventDispatcher !== null) {
$this->eventDispatcher->dispatchPackageEvent($eventName, $devMode, $repo, $allOperations, $operation);
}
@@ -389,9 +392,9 @@ private function executeBatch(InstalledRepositoryInterface $repo, array $operati
'install' => PackageEvents::POST_PACKAGE_INSTALL,
'update' => PackageEvents::POST_PACKAGE_UPDATE,
'uninstall' => PackageEvents::POST_PACKAGE_UNINSTALL,
- ][$opType] ?? null;
+ ][$opType];
- if (null !== $eventName && $runScripts && $dispatcher) {
+ if ($runScripts && $dispatcher !== null) {
$postExecCallbacks[] = static function () use ($dispatcher, $eventName, $devMode, $repo, $allOperations, $operation): void {
$dispatcher->dispatchPackageEvent($eventName, $devMode, $repo, $allOperations, $operation);
};
@@ -401,7 +404,7 @@ private function executeBatch(InstalledRepositoryInterface $repo, array $operati
}
// execute all prepare => installs/updates/removes => cleanup steps
- if (count($promises)) {
+ if (count($promises) > 0) {
$this->waitOnPromises($promises);
}
@@ -421,14 +424,14 @@ private function waitOnPromises(array $promises): void
if (
$this->outputProgress
&& $this->io instanceof ConsoleIO
- && !Platform::getEnv('CI')
+ && !((bool) Platform::getEnv('CI'))
&& !$this->io->isDebug()
&& count($promises) > 1
) {
$progress = $this->io->getProgressBar();
}
$this->loop->wait($promises, $progress);
- if ($progress) {
+ if ($progress !== null) {
$progress->clear();
// ProgressBar in non-decorated output does not output a final line-break and clear() does nothing
if (!$this->io->isDecorated()) {
@@ -573,7 +576,7 @@ public function notifyInstalls(IOInterface $io): void
try {
foreach ($this->notifiablePackages as $repoUrl => $packages) {
// non-batch API, deprecated
- if (strpos($repoUrl, '%package%')) {
+ if (str_contains($repoUrl, '%package%')) {
foreach ($packages as $package) {
$url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
@@ -635,7 +638,7 @@ public function notifyInstalls(IOInterface $io): void
private function markForNotification(PackageInterface $package): void
{
- if ($package->getNotificationUrl()) {
+ if ($package->getNotificationUrl() !== null) {
$this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
}
}
@@ -663,7 +666,7 @@ private function runCleanup(array $cleanupPromises): void
});
}
- if (!empty($promises)) {
+ if (count($promises) > 0) {
$this->loop->wait($promises);
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Installer/SuggestedPackagesReporter.php b/app/vendor/composer/composer/src/Composer/Installer/SuggestedPackagesReporter.php
index caaf81376..f33349d8d 100644
--- a/app/vendor/composer/composer/src/Composer/Installer/SuggestedPackagesReporter.php
+++ b/app/vendor/composer/composer/src/Composer/Installer/SuggestedPackagesReporter.php
@@ -200,7 +200,7 @@ private function getFilteredSuggestions(?InstalledRepository $installedRepo = nu
$suggestions = [];
foreach ($suggestedPackages as $suggestion) {
- if (in_array($suggestion['target'], $installedNames) || ($sourceFilter && !in_array($suggestion['source'], $sourceFilter))) {
+ if (in_array($suggestion['target'], $installedNames) || (\count($sourceFilter) > 0 && !in_array($suggestion['source'], $sourceFilter))) {
continue;
}
diff --git a/app/vendor/composer/composer/src/Composer/Json/JsonFile.php b/app/vendor/composer/composer/src/Composer/Json/JsonFile.php
index 7f9814d61..785e46bfa 100644
--- a/app/vendor/composer/composer/src/Composer/Json/JsonFile.php
+++ b/app/vendor/composer/composer/src/Composer/Json/JsonFile.php
@@ -32,6 +32,7 @@ class JsonFile
public const LAX_SCHEMA = 1;
public const STRICT_SCHEMA = 2;
public const AUTH_SCHEMA = 3;
+ public const LOCK_SCHEMA = 4;
/** @deprecated Use \JSON_UNESCAPED_SLASHES */
public const JSON_UNESCAPED_SLASHES = 64;
@@ -41,6 +42,7 @@ class JsonFile
public const JSON_UNESCAPED_UNICODE = 256;
public const COMPOSER_SCHEMA_PATH = __DIR__ . '/../../../res/composer-schema.json';
+ public const LOCK_SCHEMA_PATH = __DIR__ . '/../../../res/composer-lock-schema.json';
public const INDENT_DEFAULT = ' ';
@@ -228,8 +230,12 @@ public static function validateJsonSchema(string $source, $data, int $schema, ?s
{
$isComposerSchemaFile = false;
if (null === $schemaFile) {
- $isComposerSchemaFile = true;
- $schemaFile = self::COMPOSER_SCHEMA_PATH;
+ if ($schema === self::LOCK_SCHEMA) {
+ $schemaFile = self::LOCK_SCHEMA_PATH;
+ } else {
+ $isComposerSchemaFile = true;
+ $schemaFile = self::COMPOSER_SCHEMA_PATH;
+ }
}
// Prepend with file:// only when not using a special schema already (e.g. in the phar)
@@ -237,12 +243,10 @@ public static function validateJsonSchema(string $source, $data, int $schema, ?s
$schemaFile = 'file://' . $schemaFile;
}
- $schemaData = (object) ['$ref' => $schemaFile];
+ $schemaData = (object) ['$ref' => $schemaFile, '$schema' => "https://json-schema.org/draft-04/schema#"];
- if ($schema === self::LAX_SCHEMA) {
- $schemaData->additionalProperties = true;
- $schemaData->required = [];
- } elseif ($schema === self::STRICT_SCHEMA && $isComposerSchemaFile) {
+ if ($schema === self::STRICT_SCHEMA && $isComposerSchemaFile) {
+ $schemaData = json_decode((string) file_get_contents($schemaFile));
$schemaData->additionalProperties = false;
$schemaData->required = ['name', 'description'];
} elseif ($schema === self::AUTH_SCHEMA && $isComposerSchemaFile) {
@@ -250,11 +254,13 @@ public static function validateJsonSchema(string $source, $data, int $schema, ?s
}
$validator = new Validator();
- $validator->check($data, $schemaData);
+ // convert assoc arrays to objects
+ $data = json_decode((string) json_encode($data));
+ $validator->validate($data, $schemaData);
if (!$validator->isValid()) {
$errors = [];
- foreach ((array) $validator->getErrors() as $error) {
+ foreach ($validator->getErrors() as $error) {
$errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
}
throw new JsonValidationException('"'.$source.'" does not match the expected JSON schema', $errors);
@@ -284,7 +290,7 @@ public static function encode($data, int $options = 448, string $indent = self::
return Preg::replaceCallback(
'#^ {4,}#m',
static function ($match) use ($indent): string {
- return str_repeat($indent, (int)(strlen($match[0] ?? '') / 4));
+ return str_repeat($indent, (int)(strlen($match[0]) / 4));
},
$json
);
diff --git a/app/vendor/composer/composer/src/Composer/Json/JsonFormatter.php b/app/vendor/composer/composer/src/Composer/Json/JsonFormatter.php
index 006365675..fa1a3c53f 100644
--- a/app/vendor/composer/composer/src/Composer/Json/JsonFormatter.php
+++ b/app/vendor/composer/composer/src/Composer/Json/JsonFormatter.php
@@ -67,9 +67,7 @@ public static function format(string $json, bool $unescapeUnicode, bool $unescap
if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
// https://stackoverflow.com/questions/2934563/how-to-decode-unicode-escape-sequences-like-u00ed-to-proper-utf-8-encoded-cha
- $buffer = Preg::replaceCallback('/(\\\\+)u([0-9a-f]{4})/i', static function ($match) {
- assert(is_string($match[1]));
- assert(is_string($match[2]));
+ $buffer = Preg::replaceCallback('/(\\\\+)u([0-9a-f]{4})/i', static function ($match): string {
$l = strlen($match[1]);
if ($l % 2) {
diff --git a/app/vendor/composer/composer/src/Composer/Json/JsonManipulator.php b/app/vendor/composer/composer/src/Composer/Json/JsonManipulator.php
index 2e0f70411..0b45d6556 100644
--- a/app/vendor/composer/composer/src/Composer/Json/JsonManipulator.php
+++ b/app/vendor/composer/composer/src/Composer/Json/JsonManipulator.php
@@ -214,6 +214,14 @@ public function removeProperty(string $name): bool
return $this->removeSubNode('scripts', substr($name, 8));
}
+ if (strpos($name, 'autoload.') === 0) {
+ return $this->removeSubNode('autoload', substr($name, 9));
+ }
+
+ if (strpos($name, 'autoload-dev.') === 0) {
+ return $this->removeSubNode('autoload-dev', substr($name, 13));
+ }
+
return $this->removeMainKey($name);
}
@@ -280,15 +288,9 @@ public function addSubNode(string $mainNode, string $name, $value, bool $append
return $matches['start'] . $this->format($value, 1) . $matches['end'];
}, $children);
- } else {
- Preg::match('#^{ (?P\s*?) (?P\S+.*?)? (?P\s*) }$#sx', $children, $match);
-
- $whitespace = '';
- if (!empty($match['trailingspace'])) {
- $whitespace = $match['trailingspace'];
- }
-
- if (!empty($match['content'])) {
+ } elseif (Preg::isMatch('#^\{(?P\s*?)(?P\S+.*?)?(?P\s*)\}$#s', $children, $match)) {
+ $whitespace = $match['trailingspace'];
+ if (null !== $match['content']) {
if ($subName !== null) {
$value = [$subName => $value];
}
@@ -301,11 +303,7 @@ public function addSubNode(string $mainNode, string $name, $value, bool $append
$children
);
} else {
- $whitespace = '';
- if (!empty($match['leadingspace'])) {
- $whitespace = $match['leadingspace'];
- }
-
+ $whitespace = $match['leadingspace'];
$children = Preg::replace(
'#^{'.$whitespace.'#',
addcslashes('{' . $whitespace . JsonFile::encode($name).': '.$this->format($value, 1) . ',' . $this->newline . $this->indent . $this->indent, '\\$'),
@@ -320,6 +318,8 @@ public function addSubNode(string $mainNode, string $name, $value, bool $append
// children present but empty
$children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
}
+ } else {
+ throw new \LogicException('Nothing matched above for: '.$children);
}
$this->contents = Preg::replaceCallback($nodeRegex, static function ($m) use ($children): string {
@@ -403,26 +403,27 @@ public function removeSubNode(string $mainNode, string $name): bool
// no child data left, $name was the only key in
unset($match);
- Preg::match('#^{ \s*? (?P\S+.*?)? (?P\s*) }$#sx', $childrenClean, $match);
- if (empty($match['content'])) {
- $newline = $this->newline;
- $indent = $this->indent;
+ if (Preg::isMatch('#^\{\s*?(?P\S+.*?)?(?P\s*)\}$#s', $childrenClean, $match)) {
+ if (null === $match['content']) {
+ $newline = $this->newline;
+ $indent = $this->indent;
- $this->contents = Preg::replaceCallback($nodeRegex, static function ($matches) use ($indent, $newline): string {
- return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
- }, $this->contents);
+ $this->contents = Preg::replaceCallback($nodeRegex, static function ($matches) use ($indent, $newline): string {
+ return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
+ }, $this->contents);
- // we have a subname, so we restore the rest of $name
- if ($subName !== null) {
- $curVal = json_decode($children, true);
- unset($curVal[$name][$subName]);
- if ($curVal[$name] === []) {
- $curVal[$name] = new \ArrayObject();
+ // we have a subname, so we restore the rest of $name
+ if ($subName !== null) {
+ $curVal = json_decode($children, true);
+ unset($curVal[$name][$subName]);
+ if ($curVal[$name] === []) {
+ $curVal[$name] = new \ArrayObject();
+ }
+ $this->addSubNode($mainNode, $name, $curVal[$name]);
}
- $this->addSubNode($mainNode, $name, $curVal[$name]);
- }
- return true;
+ return true;
+ }
}
$this->contents = Preg::replaceCallback($nodeRegex, function ($matches) use ($name, $subName, $childrenClean): string {
diff --git a/app/vendor/composer/composer/src/Composer/PHPStan/ConfigReturnTypeExtension.php b/app/vendor/composer/composer/src/Composer/PHPStan/ConfigReturnTypeExtension.php
index e7ff6e52e..88cd635c5 100644
--- a/app/vendor/composer/composer/src/Composer/PHPStan/ConfigReturnTypeExtension.php
+++ b/app/vendor/composer/composer/src/Composer/PHPStan/ConfigReturnTypeExtension.php
@@ -61,28 +61,26 @@ public function isMethodSupported(MethodReflection $methodReflection): bool
return strtolower($methodReflection->getName()) === 'get';
}
- public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
+ public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type
{
$args = $methodCall->getArgs();
- $defaultReturn = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
-
if (count($args) < 1) {
- return $defaultReturn;
+ return null;
}
$keyType = $scope->getType($args[0]->value);
- if (method_exists($keyType, 'getConstantStrings')) { // @phpstan-ignore-line - depending on PHPStan version, this method will always exist, or not.
+ if (method_exists($keyType, 'getConstantStrings')) { // @phpstan-ignore function.alreadyNarrowedType (- depending on PHPStan version, this method will always exist, or not.)
$strings = $keyType->getConstantStrings();
} else {
// for compat with old phpstan versions, we use a deprecated phpstan method.
- $strings = TypeUtils::getConstantStrings($keyType); // @phpstan-ignore-line ignore deprecation
+ $strings = TypeUtils::getConstantStrings($keyType); // @phpstan-ignore staticMethod.deprecated (ignore deprecation)
}
if ($strings !== []) {
$types = [];
foreach($strings as $string) {
if (!isset($this->properties[$string->getValue()])) {
- return $defaultReturn;
+ return null;
}
$types[] = $this->properties[$string->getValue()];
}
@@ -90,7 +88,7 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method
return TypeCombinator::union(...$types);
}
- return $defaultReturn;
+ return null;
}
/**
diff --git a/app/vendor/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFinder.php b/app/vendor/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFinder.php
index b2b6b87b8..2cf7ffc72 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFinder.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFinder.php
@@ -47,7 +47,11 @@ public function __construct(string $sources, array $excludes, bool $ignoreFilter
{
$fs = new Filesystem();
- $sources = $fs->normalizePath(realpath($sources));
+ $sourcesRealPath = realpath($sources);
+ if ($sourcesRealPath === false) {
+ throw new \RuntimeException('Could not realpath() the source directory "'.$sources.'"');
+ }
+ $sources = $fs->normalizePath($sourcesRealPath);
if ($ignoreFilters) {
$filters = [];
@@ -61,14 +65,18 @@ public function __construct(string $sources, array $excludes, bool $ignoreFilter
$this->finder = new Finder();
$filter = static function (\SplFileInfo $file) use ($sources, $filters, $fs): bool {
- if ($file->isLink() && ($file->getRealPath() === false || strpos($file->getRealPath(), $sources) !== 0)) {
+ $realpath = $file->getRealPath();
+ if ($realpath === false) {
+ return false;
+ }
+ if ($file->isLink() && strpos($realpath, $sources) !== 0) {
return false;
}
$relativePath = Preg::replace(
'#^'.preg_quote($sources, '#').'#',
'',
- $fs->normalizePath($file->getRealPath())
+ $fs->normalizePath($realpath)
);
$exclude = false;
@@ -79,10 +87,6 @@ public function __construct(string $sources, array $excludes, bool $ignoreFilter
return !$exclude;
};
- if (method_exists($filter, 'bindTo')) {
- $filter = $filter->bindTo(null);
- }
-
$this->finder
->in($sources)
->filter($filter)
diff --git a/app/vendor/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php b/app/vendor/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php
index 4b15fa844..77c3ebe3d 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php
@@ -96,7 +96,7 @@ public function getPackageFilenameParts(CompletePackageInterface $package): arra
$sourceReference = $package->getSourceReference();
if (null !== $sourceReference) {
- $parts['source_reference'] = substr(sha1($sourceReference), 0, 6);
+ $parts['source_reference'] = substr(hash('sha1', $sourceReference), 0, 6);
}
$parts = array_filter($parts, function (?string $part) {
@@ -171,7 +171,7 @@ public function archive(CompletePackageInterface $package, string $format, strin
$sourcePath = realpath('.');
} else {
// Directory used to download the sources
- $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
+ $sourcePath = sys_get_temp_dir().'/composer_archive'.bin2hex(random_bytes(5));
$filesystem->ensureDirectoryExists($sourcePath);
try {
@@ -216,7 +216,7 @@ public function archive(CompletePackageInterface $package, string $format, strin
}
// Create the archive
- $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
+ $tempTarget = sys_get_temp_dir().'/composer_archive'.bin2hex(random_bytes(5)).'.'.$format;
$filesystem->ensureDirectoryExists(dirname($tempTarget));
$archivePath = $usableArchiver->archive(
diff --git a/app/vendor/composer/composer/src/Composer/Package/Archiver/PharArchiver.php b/app/vendor/composer/composer/src/Composer/Package/Archiver/PharArchiver.php
index c3d025f8d..6a64480ed 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Archiver/PharArchiver.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Archiver/PharArchiver.php
@@ -12,6 +12,8 @@
namespace Composer\Package\Archiver;
+use PharData;
+
/**
* @author Till Klampaeckel
* @author Nils Adermann
@@ -65,9 +67,45 @@ public function archive(string $sources, string $target, string $format, array $
$phar->buildFromIterator($filesOnly, $sources);
$filesOnly->addEmptyDir($phar, $sources);
+ if (!file_exists($target)) {
+ $target = $filename . '.' . $format;
+ unset($phar);
+
+ if ($format === 'tar') {
+ // create an empty tar file (=10240 null bytes) if the tar file is empty and PharData thus did not write it to disk
+ file_put_contents($target, str_repeat("\0", 10240));
+ } elseif ($format === 'zip') {
+ // create minimal valid ZIP file (Empty Central Directory + End of Central Directory record)
+ $eocd = pack(
+ 'VvvvvVVv',
+ 0x06054b50, // End of central directory signature
+ 0, // Number of this disk
+ 0, // Disk where central directory starts
+ 0, // Number of central directory records on this disk
+ 0, // Total number of central directory records
+ 0, // Size of central directory (bytes)
+ 0, // Offset of start of central directory
+ 0 // Comment length
+ );
+
+ file_put_contents($target, $eocd);
+ } elseif ($format === 'tar.gz' || $format === 'tar.bz2') {
+ if (!PharData::canCompress(static::$compressFormats[$format])) {
+ throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
+ }
+ if ($format === 'tar.gz' && function_exists('gzcompress')) {
+ file_put_contents($target, gzcompress(str_repeat("\0", 10240)));
+ } elseif ($format === 'tar.bz2' && function_exists('bzcompress')) {
+ file_put_contents($target, bzcompress(str_repeat("\0", 10240)));
+ }
+ }
+
+ return $target;
+ }
+
if (isset(static::$compressFormats[$format])) {
// Check can be compressed?
- if (!$phar->canCompress(static::$compressFormats[$format])) {
+ if (!PharData::canCompress(static::$compressFormats[$format])) {
throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
}
diff --git a/app/vendor/composer/composer/src/Composer/Package/Archiver/ZipArchiver.php b/app/vendor/composer/composer/src/Composer/Package/Archiver/ZipArchiver.php
index 5ab5bd55b..bc6829af9 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Archiver/ZipArchiver.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Archiver/ZipArchiver.php
@@ -12,8 +12,9 @@
namespace Composer\Package\Archiver;
-use ZipArchive;
use Composer\Util\Filesystem;
+use Composer\Util\Platform;
+use ZipArchive;
/**
* @author Jan Prieser
@@ -44,15 +45,17 @@ public function archive(string $sources, string $target, string $format, array $
$files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
foreach ($files as $file) {
/** @var \Symfony\Component\Finder\SplFileInfo $file */
- $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
- $localname = $filepath;
- if (strpos($localname, $sources . '/') === 0) {
- $localname = substr($localname, strlen($sources . '/'));
+ $filepath = $file->getPathname();
+ $relativePath = $file->getRelativePathname();
+
+ if (Platform::isWindows()) {
+ $relativePath = strtr($relativePath, '\\', '/');
}
+
if ($file->isDir()) {
- $zip->addEmptyDir($localname);
+ $zip->addEmptyDir($relativePath);
} else {
- $zip->addFile($filepath, $localname);
+ $zip->addFile($filepath, $relativePath);
}
/**
@@ -64,10 +67,26 @@ public function archive(string $sources, string $target, string $format, array $
/**
* Ensure to preserve the permission umasks for the filepath in the archive.
*/
- $zip->setExternalAttributesName($localname, ZipArchive::OPSYS_UNIX, $perms << 16);
+ $zip->setExternalAttributesName($relativePath, ZipArchive::OPSYS_UNIX, $perms << 16);
}
}
if ($zip->close()) {
+ if (!file_exists($target)) {
+ // create minimal valid ZIP file (Empty Central Directory + End of Central Directory record)
+ $eocd = pack(
+ 'VvvvvVVv',
+ 0x06054b50, // End of central directory signature
+ 0, // Number of this disk
+ 0, // Disk where central directory starts
+ 0, // Number of central directory records on this disk
+ 0, // Total number of central directory records
+ 0, // Size of central directory (bytes)
+ 0, // Offset of start of central directory
+ 0 // Comment length
+ );
+ file_put_contents($target, $eocd);
+ }
+
return $target;
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Package/BasePackage.php b/app/vendor/composer/composer/src/Composer/Package/BasePackage.php
index d6d37d360..764fdb424 100644
--- a/app/vendor/composer/composer/src/Composer/Package/BasePackage.php
+++ b/app/vendor/composer/composer/src/Composer/Package/BasePackage.php
@@ -40,8 +40,7 @@ abstract class BasePackage implements PackageInterface
public const STABILITY_ALPHA = 15;
public const STABILITY_DEV = 20;
- /** @var array */
- public static $stabilities = [
+ public const STABILITIES = [
'stable' => self::STABILITY_STABLE,
'RC' => self::STABILITY_RC,
'beta' => self::STABILITY_BETA,
@@ -49,6 +48,14 @@ abstract class BasePackage implements PackageInterface
'dev' => self::STABILITY_DEV,
];
+ /**
+ * @deprecated
+ * @readonly
+ * @var array, self::STABILITY_*>
+ * @phpstan-ignore property.readOnlyByPhpDocDefaultValue
+ */
+ public static $stabilities = self::STABILITIES;
+
/**
* READ-ONLY: The package id, public for fast access in dependency solver
* @var int
@@ -234,7 +241,7 @@ public function getFullPrettyVersion(bool $truncate = true, int $displayMode = P
*/
public function getStabilityPriority(): int
{
- return self::$stabilities[$this->getStability()];
+ return self::STABILITIES[$this->getStability()];
}
public function __clone()
diff --git a/app/vendor/composer/composer/src/Composer/Package/Comparer/Comparer.php b/app/vendor/composer/composer/src/Composer/Package/Comparer/Comparer.php
index 1fd79b8bb..70a7a28f8 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Comparer/Comparer.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Comparer/Comparer.php
@@ -136,7 +136,7 @@ private function doTree(string $dir, array &$array)
return false;
}
} elseif (is_file($dir.'/'.$file) && filesize($dir.'/'.$file)) {
- $array[$dir][$file] = md5_file($dir.'/'.$file);
+ $array[$dir][$file] = hash_file(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', $dir.'/'.$file);
}
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Package/Dumper/ArrayDumper.php b/app/vendor/composer/composer/src/Composer/Package/Dumper/ArrayDumper.php
index 046ba6674..9333bd9a0 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Dumper/ArrayDumper.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Dumper/ArrayDumper.php
@@ -37,6 +37,7 @@ public function dump(PackageInterface $package): array
'devAutoload' => 'autoload-dev',
'notificationUrl' => 'notification-url',
'includePaths' => 'include-path',
+ 'phpExt' => 'php-ext',
];
$data = [];
diff --git a/app/vendor/composer/composer/src/Composer/Package/Loader/RootPackageLoader.php b/app/vendor/composer/composer/src/Composer/Package/Loader/RootPackageLoader.php
index 64a169019..1e278a1d0 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Loader/RootPackageLoader.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Loader/RootPackageLoader.php
@@ -60,7 +60,12 @@ public function __construct(RepositoryManager $manager, Config $config, ?Version
$this->manager = $manager;
$this->config = $config;
- $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor($io), $this->versionParser);
+ if (null === $versionGuesser) {
+ $processExecutor = new ProcessExecutor($io);
+ $processExecutor->enableAsync();
+ $versionGuesser = new VersionGuesser($config, $processExecutor, $this->versionParser);
+ }
+ $this->versionGuesser = $versionGuesser;
$this->io = $io;
}
@@ -88,7 +93,7 @@ public function load(array $config, string $class = 'Composer\Package\RootPackag
// override with env var if available
if (Platform::getEnv('COMPOSER_ROOT_VERSION')) {
- $config['version'] = Platform::getEnv('COMPOSER_ROOT_VERSION');
+ $config['version'] = $this->versionGuesser->getRootVersionFromEnv();
} else {
$versionData = $this->versionGuesser->guessVersion($config, $cwd ?? Platform::getCwd(true));
if ($versionData) {
@@ -227,6 +232,7 @@ private function extractAliases(array $requires, array $aliases): array
*
* @param array $requires
* @param array $stabilityFlags
+ * @param key-of $minimumStability
*
* @return array
*
@@ -235,8 +241,7 @@ private function extractAliases(array $requires, array $aliases): array
*/
public static function extractStabilityFlags(array $requires, string $minimumStability, array $stabilityFlags): array
{
- $stabilities = BasePackage::$stabilities;
- /** @var int $minimumStability */
+ $stabilities = BasePackage::STABILITIES;
$minimumStability = $stabilities[$minimumStability];
foreach ($requires as $reqName => $reqVersion) {
$constraints = [];
diff --git a/app/vendor/composer/composer/src/Composer/Package/Loader/ValidatingArrayLoader.php b/app/vendor/composer/composer/src/Composer/Package/Loader/ValidatingArrayLoader.php
index 6d1388e23..e3600d6e1 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Loader/ValidatingArrayLoader.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Loader/ValidatingArrayLoader.php
@@ -132,33 +132,54 @@ public function load(array $config, string $class = 'Composer\Package\CompletePa
}
}
- // check for license validity on newly updated branches
- if (isset($this->config['license']) && (null === $releaseDate || $releaseDate->getTimestamp() >= strtotime('-8days'))) {
+ if (isset($this->config['license'])) {
+ // validate main data types
if (is_array($this->config['license']) || is_string($this->config['license'])) {
$licenses = (array) $this->config['license'];
- $licenseValidator = new SpdxLicenses();
- foreach ($licenses as $license) {
- // replace proprietary by MIT for validation purposes since it's not a valid SPDX identifier, but is accepted by composer
- if ('proprietary' === $license) {
- continue;
+ foreach ($licenses as $index => $license) {
+ if (!is_string($license)) {
+ $this->warnings[] = sprintf(
+ 'License %s should be a string.',
+ json_encode($license)
+ );
+ unset($licenses[$index]);
}
- $licenseToValidate = str_replace('proprietary', 'MIT', $license);
- if (!$licenseValidator->validate($licenseToValidate)) {
- if ($licenseValidator->validate(trim($licenseToValidate))) {
- $this->warnings[] = sprintf(
- 'License %s must not contain extra spaces, make sure to trim it.',
- json_encode($license)
- );
- } else {
- $this->warnings[] = sprintf(
- 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . PHP_EOL .
- 'If the software is closed-source, you may use "proprietary" as license.',
- json_encode($license)
- );
+ }
+
+ // check for license validity on newly updated branches/tags
+ if (null === $releaseDate || $releaseDate->getTimestamp() >= strtotime('-8days')) {
+ $licenseValidator = new SpdxLicenses();
+ foreach ($licenses as $license) {
+ // replace proprietary by MIT for validation purposes since it's not a valid SPDX identifier, but is accepted by composer
+ if ('proprietary' === $license) {
+ continue;
+ }
+ $licenseToValidate = str_replace('proprietary', 'MIT', $license);
+ if (!$licenseValidator->validate($licenseToValidate)) {
+ if ($licenseValidator->validate(trim($licenseToValidate))) {
+ $this->warnings[] = sprintf(
+ 'License %s must not contain extra spaces, make sure to trim it.',
+ json_encode($license)
+ );
+ } else {
+ $this->warnings[] = sprintf(
+ 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . PHP_EOL .
+ 'If the software is closed-source, you may use "proprietary" as license.',
+ json_encode($license)
+ );
+ }
}
}
}
+
+ $this->config['license'] = array_values($licenses);
+ } else {
+ $this->warnings[] = sprintf(
+ 'License must be a string or array of strings, got %s.',
+ json_encode($this->config['license'])
+ );
+ unset($this->config['license']);
}
}
@@ -323,8 +344,8 @@ public function load(array $config, string $class = 'Composer\Package\CompletePa
}
if ($this->validateString('minimum-stability') && isset($this->config['minimum-stability'])) {
- if (!isset(BasePackage::$stabilities[strtolower($this->config['minimum-stability'])]) && $this->config['minimum-stability'] !== 'RC') {
- $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
+ if (!isset(BasePackage::STABILITIES[strtolower($this->config['minimum-stability'])]) && $this->config['minimum-stability'] !== 'RC') {
+ $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::STABILITIES));
unset($this->config['minimum-stability']);
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Package/Locker.php b/app/vendor/composer/composer/src/Composer/Package/Locker.php
index f832e797c..38cd8ef3a 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Locker.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Locker.php
@@ -66,13 +66,21 @@ public function __construct(IOInterface $io, JsonFile $lockFile, InstallationMan
{
$this->lockFile = $lockFile;
$this->installationManager = $installationManager;
- $this->hash = md5($composerFileContents);
+ $this->hash = hash('md5', $composerFileContents);
$this->contentHash = self::getContentHash($composerFileContents);
$this->loader = new ArrayLoader(null, true);
$this->dumper = new ArrayDumper();
$this->process = $process ?? new ProcessExecutor($io);
}
+ /**
+ * @internal
+ */
+ public function getJsonFile(): JsonFile
+ {
+ return $this->lockFile;
+ }
+
/**
* Returns the md5 hash of the sorted content of the composer file.
*
@@ -107,7 +115,7 @@ public static function getContentHash(string $composerFileContents): string
ksort($relevantContent);
- return md5(JsonFile::encode($relevantContent, 0));
+ return hash('md5', JsonFile::encode($relevantContent, 0));
}
/**
@@ -247,6 +255,9 @@ public function getPlatformRequirements(bool $withDevReqs = false): array
return $requirements;
}
+ /**
+ * @return key-of
+ */
public function getMinimumStability(): string
{
$lockData = $this->getLockData();
@@ -361,7 +372,7 @@ public function setLockData(array $packages, ?array $devPackages, array $platfor
'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies',
'This file is @gener'.'ated automatically', ],
'content-hash' => $this->contentHash,
- 'packages' => null,
+ 'packages' => $this->lockPackages($packages),
'packages-dev' => null,
'aliases' => $aliases,
'minimum-stability' => $minimumStability,
@@ -370,7 +381,6 @@ public function setLockData(array $packages, ?array $devPackages, array $platfor
'prefer-lowest' => $preferLowest,
];
- $lock['packages'] = $this->lockPackages($packages);
if (null !== $devPackages) {
$lock['packages-dev'] = $this->lockPackages($devPackages);
}
@@ -382,6 +392,8 @@ public function setLockData(array $packages, ?array $devPackages, array $platfor
}
$lock['plugin-api-version'] = PluginInterface::PLUGIN_API_VERSION;
+ $lock = $this->fixupJsonDataType($lock);
+
try {
$isLocked = $this->isLocked();
} catch (ParsingException $e) {
@@ -403,6 +415,60 @@ public function setLockData(array $packages, ?array $devPackages, array $platfor
return false;
}
+ /**
+ * Updates the lock file's hash in-place from a given composer.json's JsonFile
+ *
+ * This does not reload or require any packages, and retains the filemtime of the lock file.
+ *
+ * Use this only to update the lock file hash after updating a composer.json in ways that are guaranteed NOT to impact the dependency resolution.
+ *
+ * This is a risky method, use carefully.
+ *
+ * @param (callable(array): array)|null $dataProcessor Receives the lock data and can process it before it gets written to disk
+ */
+ public function updateHash(JsonFile $composerJson, ?callable $dataProcessor = null): void
+ {
+ $contents = file_get_contents($composerJson->getPath());
+ if (false === $contents) {
+ throw new \RuntimeException('Unable to read '.$composerJson->getPath().' contents to update the lock file hash.');
+ }
+
+ $lockMtime = filemtime($this->lockFile->getPath());
+ $lockData = $this->lockFile->read();
+ $lockData['content-hash'] = Locker::getContentHash($contents);
+ if ($dataProcessor !== null) {
+ $lockData = $dataProcessor($lockData);
+ }
+
+ $this->lockFile->write($this->fixupJsonDataType($lockData));
+ $this->lockDataCache = null;
+ $this->virtualFileWritten = false;
+ if (is_int($lockMtime)) {
+ @touch($this->lockFile->getPath(), $lockMtime);
+ }
+ }
+
+ /**
+ * Ensures correct data types and ordering for the JSON lock format
+ *
+ * @param array $lockData
+ * @return array
+ */
+ private function fixupJsonDataType(array $lockData): array
+ {
+ foreach (['stability-flags', 'platform', 'platform-dev'] as $key) {
+ if (isset($lockData[$key]) && is_array($lockData[$key]) && \count($lockData[$key]) === 0) {
+ $lockData[$key] = new \stdClass();
+ }
+ }
+
+ if (is_array($lockData['stability-flags'])) {
+ ksort($lockData['stability-flags']);
+ }
+
+ return $lockData;
+ }
+
/**
* @param PackageInterface[] $packages
*
@@ -488,13 +554,14 @@ private function getPackageTime(PackageInterface $package): ?string
case 'git':
GitUtil::cleanEnv();
- if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef).GitUtil::getNoShowSignatureFlag($this->process), $output, $path) && Preg::isMatch('{^\s*\d+\s*$}', $output)) {
+ $command = array_merge(['git', 'log', '-n1', '--pretty=%ct', (string) $sourceRef], GitUtil::getNoShowSignatureFlags($this->process));
+ if (0 === $this->process->execute($command, $output, $path) && Preg::isMatch('{^\s*\d+\s*$}', $output)) {
$datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
}
break;
case 'hg':
- if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && Preg::isMatch('{^\s*(\d+)\s*}', $output, $match)) {
+ if (0 === $this->process->execute(['hg', 'log', '--template', '{date|hgdate}', '-r', (string) $sourceRef], $output, $path) && Preg::isMatch('{^\s*(\d+)\s*}', $output, $match)) {
$datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
}
break;
diff --git a/app/vendor/composer/composer/src/Composer/Package/Package.php b/app/vendor/composer/composer/src/Composer/Package/Package.php
index 9d1b0ffc1..faa2a07a0 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Package.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Package.php
@@ -23,6 +23,7 @@
*
* @phpstan-import-type AutoloadRules from PackageInterface
* @phpstan-import-type DevAutoloadRules from PackageInterface
+ * @phpstan-import-type PhpExtConfig from PackageInterface
*/
class Package extends BasePackage
{
@@ -98,7 +99,10 @@ class Package extends BasePackage
protected $isDefaultBranch = false;
/** @var mixed[] */
protected $transportOptions = [];
- /** @var array{priority?: int, configure-options?: list}|null */
+ /**
+ * @var array|null
+ * @phpstan-var PhpExtConfig|null
+ */
protected $phpExt = null;
/**
@@ -593,9 +597,11 @@ public function getIncludePaths(): array
}
/**
- * Sets the list of paths added to PHP's include path.
+ * Sets the settings for php extension packages
+ *
+ * @param array|null $phpExt
*
- * @param array{extension-name?: string, priority?: int, support-zts?: bool, configure-options?: list}|null $phpExt List of directories.
+ * @phpstan-param PhpExtConfig|null $phpExt
*/
public function setPhpExt(?array $phpExt): void
{
diff --git a/app/vendor/composer/composer/src/Composer/Package/PackageInterface.php b/app/vendor/composer/composer/src/Composer/Package/PackageInterface.php
index b7c9ecd45..68e22fa0e 100644
--- a/app/vendor/composer/composer/src/Composer/Package/PackageInterface.php
+++ b/app/vendor/composer/composer/src/Composer/Package/PackageInterface.php
@@ -23,6 +23,7 @@
*
* @phpstan-type AutoloadRules array{psr-0?: array, psr-4?: array, classmap?: list, files?: list, exclude-from-classmap?: list}
* @phpstan-type DevAutoloadRules array{psr-0?: array, psr-4?: array, classmap?: list, files?: list}
+ * @phpstan-type PhpExtConfig array{extension-name?: string, priority?: int, support-zts?: bool, support-nts?: bool, build-path?: string|null, download-url-method?: string, os-families?: non-empty-list, os-families-exclude?: non-empty-list, configure-options?: list}
*/
interface PackageInterface
{
@@ -326,7 +327,9 @@ public function getIncludePaths(): array;
/**
* Returns the settings for php extension packages
*
- * @return array{extension-name?: string, priority?: int, support-zts?: bool, configure-options?: list}|null
+ * @return array|null
+ *
+ * @phpstan-return PhpExtConfig|null
*/
public function getPhpExt(): ?array;
diff --git a/app/vendor/composer/composer/src/Composer/Package/RootPackage.php b/app/vendor/composer/composer/src/Composer/Package/RootPackage.php
index e1305426f..a0f8e659f 100644
--- a/app/vendor/composer/composer/src/Composer/Package/RootPackage.php
+++ b/app/vendor/composer/composer/src/Composer/Package/RootPackage.php
@@ -21,7 +21,7 @@ class RootPackage extends CompletePackage implements RootPackageInterface
{
public const DEFAULT_PRETTY_VERSION = '1.0.0+no-version-set';
- /** @var string */
+ /** @var key-of */
protected $minimumStability = 'stable';
/** @var bool */
protected $preferStable = false;
diff --git a/app/vendor/composer/composer/src/Composer/Package/RootPackageInterface.php b/app/vendor/composer/composer/src/Composer/Package/RootPackageInterface.php
index 4adad6c8b..8a08060f8 100644
--- a/app/vendor/composer/composer/src/Composer/Package/RootPackageInterface.php
+++ b/app/vendor/composer/composer/src/Composer/Package/RootPackageInterface.php
@@ -33,6 +33,8 @@ public function getAliases(): array;
/**
* Returns the minimum stability of the package
+ *
+ * @return key-of
*/
public function getMinimumStability(): string;
@@ -120,12 +122,14 @@ public function setDevAutoload(array $devAutoload): void;
/**
* Set the stabilityFlags
*
- * @param array $stabilityFlags
+ * @phpstan-param array $stabilityFlags
*/
public function setStabilityFlags(array $stabilityFlags): void;
/**
* Set the minimumStability
+ *
+ * @phpstan-param key-of $minimumStability
*/
public function setMinimumStability(string $minimumStability): void;
diff --git a/app/vendor/composer/composer/src/Composer/Package/Version/StabilityFilter.php b/app/vendor/composer/composer/src/Composer/Package/Version/StabilityFilter.php
index 172901d44..7e0182a6e 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Version/StabilityFilter.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Version/StabilityFilter.php
@@ -23,11 +23,11 @@ class StabilityFilter
* Checks if any of the provided package names in the given stability match the configured acceptable stability and flags
*
* @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value
- * @phpstan-param array $acceptableStabilities
+ * @phpstan-param array, BasePackage::STABILITY_*> $acceptableStabilities
* @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
* @phpstan-param array $stabilityFlags
* @param string[] $names The package name(s) to check for stability flags
- * @param string $stability one of 'stable', 'RC', 'beta', 'alpha' or 'dev'
+ * @param key-of $stability one of 'stable', 'RC', 'beta', 'alpha' or 'dev'
* @return bool true if any package name is acceptable
*/
public static function isPackageAcceptable(array $acceptableStabilities, array $stabilityFlags, array $names, string $stability): bool
@@ -35,7 +35,7 @@ public static function isPackageAcceptable(array $acceptableStabilities, array $
foreach ($names as $name) {
// allow if package matches the package-specific stability flag
if (isset($stabilityFlags[$name])) {
- if (BasePackage::$stabilities[$stability] <= $stabilityFlags[$name]) {
+ if (BasePackage::STABILITIES[$stability] <= $stabilityFlags[$name]) {
return true;
}
} elseif (isset($acceptableStabilities[$stability])) {
diff --git a/app/vendor/composer/composer/src/Composer/Package/Version/VersionBumper.php b/app/vendor/composer/composer/src/Composer/Package/Version/VersionBumper.php
index e6dbdebe6..b100d0e00 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Version/VersionBumper.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Version/VersionBumper.php
@@ -39,6 +39,8 @@ class VersionBumper
* * ^1.2 || ^2.3 + 2.4.0 -> ^1.2 || ^2.4
* * ^3@dev + 3.2.99999-dev -> ^3.2@dev
* * ~2 + 2.0-beta.1 -> ~2
+ * * ~2.0.0 + 2.0.3 -> ~2.0.3
+ * * ~2.0 + 2.0.3 -> ^2.0.3
* * dev-master + dev-master -> dev-master
* * * + 1.2.3 -> >=1.2.3
*/
@@ -84,7 +86,7 @@ public function bumpRequirement(ConstraintInterface $constraint, PackageInterfac
(?<=,|\ |\||^) # leading separator
(?P
\^v?'.$major.'(?:\.\d+)* # e.g. ^2.anything
- | ~v?'.$major.'(?:\.\d+){0,2} # e.g. ~2 or ~2.2 or ~2.2.2 but no more
+ | ~v?'.$major.'(?:\.\d+){1,3} # e.g. ~2.2 or ~2.2.2 or ~2.2.2.2
| v?'.$major.'(?:\.[*x])+ # e.g. 2.* or 2.*.* or 2.x.x.x etc
| >=v?\d(?:\.\d+)* # e.g. >=2 or >=1.2 etc
| \* # full wildcard
@@ -99,8 +101,11 @@ public function bumpRequirement(ConstraintInterface $constraint, PackageInterfac
if (substr_count($match[0], '.') === 2 && substr_count($versionWithoutSuffix, '.') === 1) {
$suffix = '.0';
}
- if (str_starts_with($match[0], '~') && substr_count($match[0], '.') === 2) {
- $replacement = '~'.$versionWithoutSuffix.$suffix;
+ if (str_starts_with($match[0], '~') && substr_count($match[0], '.') !== 1) {
+ // take as many version bits from the current version as we have in the constraint to bump it without making it more specific
+ $versionBits = explode('.', $versionWithoutSuffix);
+ $versionBits = array_pad($versionBits, substr_count($match[0], '.') + 1, '0');
+ $replacement = '~'.implode('.', array_slice($versionBits, 0, substr_count($match[0], '.') + 1));
} elseif ($match[0] === '*' || str_starts_with($match[0], '>=')) {
$replacement = '>='.$versionWithoutSuffix.$suffix;
} else {
diff --git a/app/vendor/composer/composer/src/Composer/Package/Version/VersionGuesser.php b/app/vendor/composer/composer/src/Composer/Package/Version/VersionGuesser.php
index 2b2b19706..7e0f8278e 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Version/VersionGuesser.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Version/VersionGuesser.php
@@ -13,6 +13,7 @@
namespace Composer\Package\Version;
use Composer\Config;
+use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
use Composer\Repository\Vcs\HgDriver;
use Composer\IO\NullIO;
@@ -50,11 +51,17 @@ class VersionGuesser
*/
private $versionParser;
- public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
+ /**
+ * @var IOInterface|null
+ */
+ private $io;
+
+ public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser, ?IOInterface $io = null)
{
$this->config = $config;
$this->process = $process;
$this->versionParser = $versionParser;
+ $this->io = $io;
}
/**
@@ -173,11 +180,12 @@ private function guessGitVersion(array $packageConfig, string $path): array
$featurePrettyVersion = $prettyVersion;
// try to find the best (nearest) version branch to assume this feature's version
- $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
+ $result = $this->guessFeatureVersion($packageConfig, $version, $branches, ['git', 'rev-list', '%candidate%..%branch%'], $path);
$version = $result['version'];
$prettyVersion = $result['pretty_version'];
}
}
+ GitUtil::checkForRepoOwnershipError($this->process->getErrorOutput(), $path, $this->io);
if (!$version || $isDetached) {
$result = $this->versionFromGitTags($path);
@@ -190,7 +198,7 @@ private function guessGitVersion(array $packageConfig, string $path): array
}
if (null === $commit) {
- $command = 'git log --pretty="%H" -n1 HEAD'.GitUtil::getNoShowSignatureFlag($this->process);
+ $command = array_merge(['git', 'log', '--pretty=%H', '-n1', 'HEAD'], GitUtil::getNoShowSignatureFlags($this->process));
if (0 === $this->process->execute($command, $output, $path)) {
$commit = trim($output) ?: null;
}
@@ -209,7 +217,7 @@ private function guessGitVersion(array $packageConfig, string $path): array
private function versionFromGitTags(string $path): ?array
{
// try to fetch current version from git tags
- if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
+ if (0 === $this->process->execute(['git', 'describe', '--exact-match', '--tags'], $output, $path)) {
try {
$version = $this->versionParser->normalize(trim($output));
@@ -229,7 +237,7 @@ private function versionFromGitTags(string $path): ?array
private function guessHgVersion(array $packageConfig, string $path): ?array
{
// try to fetch current version from hg branch
- if (0 === $this->process->execute('hg branch', $output, $path)) {
+ if (0 === $this->process->execute(['hg', 'branch'], $output, $path)) {
$branch = trim($output);
$version = $this->versionParser->normalizeBranch($branch);
$isFeatureBranch = 0 === strpos($version, 'dev-');
@@ -248,7 +256,7 @@ private function guessHgVersion(array $packageConfig, string $path): ?array
$branches = array_map('strval', array_keys($driver->getBranches()));
// try to find the best (nearest) version branch to assume this feature's version
- $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
+ $result = $this->guessFeatureVersion($packageConfig, $version, $branches, ['hg', 'log', '-r', 'not ancestors(\'%candidate%\') and ancestors(\'%branch%\')', '--template', '"{node}\\n"'], $path);
$result['commit'] = '';
$result['feature_version'] = $version;
$result['feature_pretty_version'] = $version;
@@ -261,13 +269,12 @@ private function guessHgVersion(array $packageConfig, string $path): ?array
/**
* @param array $packageConfig
- * @param string[] $branches
- *
- * @phpstan-param non-empty-string $scmCmdline
+ * @param list $branches
+ * @param list $scmCmdline
*
* @return array{version: string|null, pretty_version: string|null}
*/
- private function guessFeatureVersion(array $packageConfig, ?string $version, array $branches, string $scmCmdline, string $path): array
+ private function guessFeatureVersion(array $packageConfig, ?string $version, array $branches, array $scmCmdline, string $path): array
{
$prettyVersion = $version;
@@ -285,7 +292,7 @@ private function guessFeatureVersion(array $packageConfig, ?string $version, arr
}
// sort local branches first then remote ones
- // and sort numeric branches below named ones, to make sure if the branch has the same distance from main and 1.10 and 1.9 for example, main is picked
+ // and sort numeric branches below named ones, to make sure if the branch has the same distance from main and 1.10 and 1.9 for example, 1.9 is picked
// and sort using natural sort so that 1.10 will appear before 1.9
usort($branches, static function ($a, $b): int {
$aRemote = 0 === strpos($a, 'remotes/');
@@ -301,7 +308,8 @@ private function guessFeatureVersion(array $packageConfig, ?string $version, arr
$promises = [];
$this->process->setMaxJobs(30);
try {
- foreach ($branches as $candidate) {
+ $lastIndex = -1;
+ foreach ($branches as $index => $candidate) {
$candidateVersion = Preg::replace('{^remotes/\S+/}', '', $candidate);
// do not compare against itself or other feature branches
@@ -309,14 +317,20 @@ private function guessFeatureVersion(array $packageConfig, ?string $version, arr
continue;
}
- $cmdLine = str_replace(['%candidate%', '%branch%'], [$candidate, $branch], $scmCmdline);
- $promises[] = $this->process->executeAsync($cmdLine, $path)->then(function (Process $process) use (&$length, &$version, &$prettyVersion, $candidateVersion, &$promises): void {
+ $cmdLine = array_map(static function (string $component) use ($candidate, $branch) {
+ return str_replace(['%candidate%', '%branch%'], [$candidate, $branch], $component);
+ }, $scmCmdline);
+ $promises[] = $this->process->executeAsync($cmdLine, $path)->then(function (Process $process) use (&$lastIndex, $index, &$length, &$version, &$prettyVersion, $candidateVersion, &$promises): void {
if (!$process->isSuccessful()) {
return;
}
$output = $process->getOutput();
- if (strlen($output) < $length) {
+ // overwrite existing if we have a shorter diff, or we have an equal diff and an index that comes later in the array (i.e. older version)
+ // as newer versions typically have more commits, if the feature branch is based on a newer branch it should have a longer diff to the old version
+ // but if it doesn't and they have equal diffs, then it probably is based on the old version
+ if (strlen($output) < $length || (strlen($output) === $length && $lastIndex < $index)) {
+ $lastIndex = $index;
$length = strlen($output);
$version = $this->versionParser->normalizeBranch($candidateVersion);
$prettyVersion = 'dev-' . $candidateVersion;
@@ -361,14 +375,14 @@ private function guessFossilVersion(string $path): array
$prettyVersion = null;
// try to fetch current version from fossil
- if (0 === $this->process->execute('fossil branch list', $output, $path)) {
+ if (0 === $this->process->execute(['fossil', 'branch', 'list'], $output, $path)) {
$branch = trim($output);
$version = $this->versionParser->normalizeBranch($branch);
$prettyVersion = 'dev-' . $branch;
}
// try to fetch current version from fossil tags
- if (0 === $this->process->execute('fossil tag list', $output, $path)) {
+ if (0 === $this->process->execute(['fossil', 'tag', 'list'], $output, $path)) {
try {
$version = $this->versionParser->normalize(trim($output));
$prettyVersion = trim($output);
@@ -389,7 +403,7 @@ private function guessSvnVersion(array $packageConfig, string $path): ?array
SvnUtil::cleanEnv();
// try to fetch current version from svn
- if (0 === $this->process->execute('svn info --xml', $output, $path)) {
+ if (0 === $this->process->execute(['svn', 'info', '--xml'], $output, $path)) {
$trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
$branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
$tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
@@ -419,4 +433,17 @@ private function guessSvnVersion(array $packageConfig, string $path): ?array
return null;
}
+
+ public function getRootVersionFromEnv(): string
+ {
+ $version = Platform::getEnv('COMPOSER_ROOT_VERSION');
+ if (!is_string($version) || $version === '') {
+ throw new \RuntimeException('COMPOSER_ROOT_VERSION not set or empty');
+ }
+ if (Preg::isMatch('{^(\d+(?:\.\d+)*)-dev$}i', $version, $match)) {
+ $version = $match[1].'.x-dev';
+ }
+
+ return $version;
+ }
}
diff --git a/app/vendor/composer/composer/src/Composer/Package/Version/VersionSelector.php b/app/vendor/composer/composer/src/Composer/Package/Version/VersionSelector.php
index 9ab322084..7c0c61a31 100644
--- a/app/vendor/composer/composer/src/Composer/Package/Version/VersionSelector.php
+++ b/app/vendor/composer/composer/src/Composer/Package/Version/VersionSelector.php
@@ -71,7 +71,7 @@ public function __construct(RepositorySet $repositorySet, ?PlatformRepository $p
*/
public function findBestCandidate(string $packageName, ?string $targetPackageVersion = null, string $preferredStability = 'stable', $platformRequirementFilter = null, int $repoSetFlags = 0, ?IOInterface $io = null, $showWarnings = true)
{
- if (!isset(BasePackage::$stabilities[$preferredStability])) {
+ if (!isset(BasePackage::STABILITIES[$preferredStability])) {
// If you get this, maybe you are still relying on the Composer 1.x signature where the 3rd arg was the php version
throw new \UnexpectedValueException('Expected a valid stability name as 3rd argument, got '.$preferredStability);
}
@@ -86,7 +86,7 @@ public function findBestCandidate(string $packageName, ?string $targetPackageVer
$constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
$candidates = $this->repositorySet->findPackages(strtolower($packageName), $constraint, $repoSetFlags);
- $minPriority = BasePackage::$stabilities[$preferredStability];
+ $minPriority = BasePackage::STABILITIES[$preferredStability];
usort($candidates, static function (PackageInterface $a, PackageInterface $b) use ($minPriority) {
$aPriority = $a->getStabilityPriority();
$bPriority = $b->getStabilityPriority();
@@ -121,6 +121,7 @@ public function findBestCandidate(string $packageName, ?string $targetPackageVer
foreach ($candidates as $pkg) {
$reqs = $pkg->getRequires();
+ $skip = false;
foreach ($reqs as $name => $link) {
if (!PlatformRepository::isPlatformPackage($name) || $platformRequirementFilter->isIgnored($name)) {
continue;
@@ -151,8 +152,8 @@ public function findBestCandidate(string $packageName, ?string $targetPackageVer
$isLatestVersion = !isset($alreadySeenNames[$pkg->getName()]);
$alreadySeenNames[$pkg->getName()] = true;
if ($io !== null && ($showWarnings === true || (is_callable($showWarnings) && $showWarnings($pkg)))) {
- $isFirstWarning = !isset($alreadyWarnedNames[$pkg->getName()]);
- $alreadyWarnedNames[$pkg->getName()] = true;
+ $isFirstWarning = !isset($alreadyWarnedNames[$pkg->getName().'/'.$link->getTarget()]);
+ $alreadyWarnedNames[$pkg->getName().'/'.$link->getTarget()] = true;
$latest = $isLatestVersion ? "'s latest version" : '';
$io->writeError(
'Cannot use '.$pkg->getPrettyName().$latest.' '.$pkg->getPrettyVersion().' as it '.$link->getDescription().' '.$link->getTarget().' '.$link->getPrettyConstraint().' which '.$reason.'.>',
@@ -162,7 +163,11 @@ public function findBestCandidate(string $packageName, ?string $targetPackageVer
}
// skip candidate
- continue 2;
+ $skip = true;
+ }
+
+ if ($skip) {
+ continue;
}
$package = $pkg;
diff --git a/app/vendor/composer/composer/src/Composer/PartialComposer.php b/app/vendor/composer/composer/src/Composer/PartialComposer.php
index c6f9c7523..f4b7910a8 100644
--- a/app/vendor/composer/composer/src/Composer/PartialComposer.php
+++ b/app/vendor/composer/composer/src/Composer/PartialComposer.php
@@ -23,6 +23,11 @@
*/
class PartialComposer
{
+ /**
+ * @var bool
+ */
+ private $global = false;
+
/**
* @var RootPackageInterface
*/
@@ -112,4 +117,14 @@ public function getEventDispatcher(): EventDispatcher
{
return $this->eventDispatcher;
}
+
+ public function isGlobal(): bool
+ {
+ return $this->global;
+ }
+
+ public function setGlobal(): void
+ {
+ $this->global = true;
+ }
}
diff --git a/app/vendor/composer/composer/src/Composer/Platform/HhvmDetector.php b/app/vendor/composer/composer/src/Composer/Platform/HhvmDetector.php
index 46886c353..284b0ba8a 100644
--- a/app/vendor/composer/composer/src/Composer/Platform/HhvmDetector.php
+++ b/app/vendor/composer/composer/src/Composer/Platform/HhvmDetector.php
@@ -49,11 +49,7 @@ public function getVersion(): ?string
$hhvmPath = $this->executableFinder->find('hhvm');
if ($hhvmPath !== null) {
$this->processExecutor = $this->processExecutor ?? new ProcessExecutor();
- $exitCode = $this->processExecutor->execute(
- ProcessExecutor::escape($hhvmPath).
- ' --php -d hhvm.jit=0 -r "echo HHVM_VERSION;" 2>/dev/null',
- self::$hhvmVersion
- );
+ $exitCode = $this->processExecutor->execute([$hhvmPath, '--php', '-d', 'hhvm.jit=0', '-r', 'echo HHVM_VERSION;'], self::$hhvmVersion);
if ($exitCode !== 0) {
self::$hhvmVersion = false;
}
diff --git a/app/vendor/composer/composer/src/Composer/Platform/Runtime.php b/app/vendor/composer/composer/src/Composer/Platform/Runtime.php
index b05af085c..940c02d0f 100644
--- a/app/vendor/composer/composer/src/Composer/Platform/Runtime.php
+++ b/app/vendor/composer/composer/src/Composer/Platform/Runtime.php
@@ -56,9 +56,12 @@ public function hasClass(string $class): bool
}
/**
- * @param class-string $class
+ * @template T of object
* @param mixed[] $arguments
*
+ * @phpstan-param class-string $class
+ * @phpstan-return T
+ *
* @throws \ReflectionException
*/
public function construct(string $class, array $arguments = []): object
diff --git a/app/vendor/composer/composer/src/Composer/Plugin/PluginManager.php b/app/vendor/composer/composer/src/Composer/Plugin/PluginManager.php
index f594478a6..8a6fad2cb 100644
--- a/app/vendor/composer/composer/src/Composer/Plugin/PluginManager.php
+++ b/app/vendor/composer/composer/src/Composer/Plugin/PluginManager.php
@@ -20,11 +20,13 @@
use Composer\Package\CompletePackage;
use Composer\Package\Locker;
use Composer\Package\Package;
+use Composer\Package\RootPackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\PartialComposer;
use Composer\Pcre\Preg;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\InstalledRepository;
+use Composer\Repository\RepositoryUtils;
use Composer\Repository\RootPackageRepository;
use Composer\Package\PackageInterface;
use Composer\Package\Link;
@@ -53,7 +55,7 @@ class PluginManager
/** @var array */
protected $plugins = [];
- /** @var array */
+ /** @var array> */
protected $registeredPlugins = [];
/**
@@ -98,7 +100,7 @@ public function loadInstalledPlugins(): void
{
if (!$this->arePluginsDisabled('local')) {
$repo = $this->composer->getRepositoryManager()->getLocalRepository();
- $this->loadRepository($repo, false);
+ $this->loadRepository($repo, false, $this->composer->getPackage());
}
if ($this->globalComposer !== null && !$this->arePluginsDisabled('global')) {
@@ -287,14 +289,14 @@ public function registerPackage(PackageInterface $package, bool $failOnMissingCl
$this->io->writeError('Loading "'.$package->getName() . '" '.($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '').'which is a legacy composer-installer built for Composer 1.x, it is likely to cause issues as you are running Composer 2.x.');
$installer = new $class($this->io, $this->composer);
$this->composer->getInstallationManager()->addInstaller($installer);
- $this->registeredPlugins[$package->getName()] = $installer;
+ $this->registeredPlugins[$package->getName()][] = $installer;
} elseif (class_exists($class)) {
if (!is_a($class, 'Composer\Plugin\PluginInterface', true)) {
throw new \RuntimeException('Could not activate plugin "'.$package->getName().'" as "'.$class.'" does not implement Composer\Plugin\PluginInterface');
}
$plugin = new $class();
$this->addPlugin($plugin, $isGlobalPlugin, $package);
- $this->registeredPlugins[$package->getName()] = $plugin;
+ $this->registeredPlugins[$package->getName()][] = $plugin;
} elseif ($failOnMissingClasses) {
throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
}
@@ -315,13 +317,15 @@ public function deactivatePackage(PackageInterface $package): void
return;
}
- $plugin = $this->registeredPlugins[$package->getName()];
- unset($this->registeredPlugins[$package->getName()]);
- if ($plugin instanceof InstallerInterface) {
- $this->composer->getInstallationManager()->removeInstaller($plugin);
- } else {
- $this->removePlugin($plugin);
+ $plugins = $this->registeredPlugins[$package->getName()];
+ foreach ($plugins as $plugin) {
+ if ($plugin instanceof InstallerInterface) {
+ $this->composer->getInstallationManager()->removeInstaller($plugin);
+ } else {
+ $this->removePlugin($plugin);
+ }
}
+ unset($this->registeredPlugins[$package->getName()]);
}
/**
@@ -338,14 +342,16 @@ public function uninstallPackage(PackageInterface $package): void
return;
}
- $plugin = $this->registeredPlugins[$package->getName()];
- if ($plugin instanceof InstallerInterface) {
- $this->deactivatePackage($package);
- } else {
- unset($this->registeredPlugins[$package->getName()]);
- $this->removePlugin($plugin);
- $this->uninstallPlugin($plugin);
+ $plugins = $this->registeredPlugins[$package->getName()];
+ foreach ($plugins as $plugin) {
+ if ($plugin instanceof InstallerInterface) {
+ $this->composer->getInstallationManager()->removeInstaller($plugin);
+ } else {
+ $this->removePlugin($plugin);
+ $this->uninstallPlugin($plugin);
+ }
}
+ unset($this->registeredPlugins[$package->getName()]);
}
/**
@@ -445,9 +451,11 @@ public function uninstallPlugin(PluginInterface $plugin): void
*
* @param RepositoryInterface $repo Repository to scan for plugins to install
*
+ * @phpstan-param ($isGlobalRepo is true ? null : RootPackageInterface) $rootPackage
+ *
* @throws \RuntimeException
*/
- private function loadRepository(RepositoryInterface $repo, bool $isGlobalRepo): void
+ private function loadRepository(RepositoryInterface $repo, bool $isGlobalRepo, ?RootPackageInterface $rootPackage = null): void
{
$packages = $repo->getPackages();
@@ -462,10 +470,28 @@ private function loadRepository(RepositoryInterface $repo, bool $isGlobalRepo):
}
$sortedPackages = PackageSorter::sortPackages($packages, $weights);
+ if (!$isGlobalRepo) {
+ $requiredPackages = RepositoryUtils::filterRequiredPackages($packages, $rootPackage, true);
+ }
+
foreach ($sortedPackages as $package) {
if (!($package instanceof CompletePackage)) {
continue;
}
+
+ if (!in_array($package->getType(), ['composer-plugin', 'composer-installer'], true)) {
+ continue;
+ }
+
+ if (
+ !$isGlobalRepo
+ && !in_array($package, $requiredPackages, true)
+ && !$this->isPluginAllowed($package->getName(), false, true, false)
+ ) {
+ $this->io->writeError('The "'.$package->getName().'" plugin was not loaded as it is not listed in allow-plugins and is not required by the root package anymore.');
+ continue;
+ }
+
if ('composer-plugin' === $package->getType()) {
$this->registerPackage($package, false, $isGlobalRepo);
// Backward compatibility
@@ -668,7 +694,7 @@ public function disablePlugins(): void
/**
* @internal
*/
- public function isPluginAllowed(string $package, bool $isGlobalPlugin, bool $optional = false): bool
+ public function isPluginAllowed(string $package, bool $isGlobalPlugin, bool $optional = false, bool $prompt = true): bool
{
if ($isGlobalPlugin) {
$rules = &$this->allowGlobalPluginRules;
@@ -703,7 +729,7 @@ public function isPluginAllowed(string $package, bool $isGlobalPlugin, bool $opt
return false;
}
- if ($this->io->isInteractive()) {
+ if ($this->io->isInteractive() && $prompt) {
$composer = $isGlobalPlugin && $this->globalComposer !== null ? $this->globalComposer : $this->composer;
$this->io->writeError(''.$package.($isGlobalPlugin || $this->runningInGlobalDir ? ' (installed globally)' : '').' contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins');
@@ -728,7 +754,15 @@ public function isPluginAllowed(string $package, bool $isGlobalPlugin, bool $opt
// persist answer in composer.json if it wasn't simply discarded
if ($answer === 'y' || $answer === 'n') {
- $composer->getConfig()->getConfigSource()->addConfigSetting('allow-plugins.'.$package, $allow);
+ $allowPlugins = $composer->getConfig()->get('allow-plugins');
+ if (is_array($allowPlugins)) {
+ $allowPlugins[$package] = $allow;
+ if ($composer->getConfig()->get('sort-packages')) {
+ ksort($allowPlugins);
+ }
+ $composer->getConfig()->getConfigSource()->addConfigSetting('allow-plugins', $allowPlugins);
+ $composer->getConfig()->merge(['config' => ['allow-plugins' => $allowPlugins]]);
+ }
}
return $allow;
diff --git a/app/vendor/composer/composer/src/Composer/Plugin/PostFileDownloadEvent.php b/app/vendor/composer/composer/src/Composer/Plugin/PostFileDownloadEvent.php
index e78991646..a8d9a025f 100644
--- a/app/vendor/composer/composer/src/Composer/Plugin/PostFileDownloadEvent.php
+++ b/app/vendor/composer/composer/src/Composer/Plugin/PostFileDownloadEvent.php
@@ -59,7 +59,7 @@ class PostFileDownloadEvent extends Event
*/
public function __construct(string $name, ?string $fileName, ?string $checksum, string $url, string $type, $context = null)
{
- /** @phpstan-ignore-next-line */
+ /** @phpstan-ignore instanceof.alwaysFalse, booleanAnd.alwaysFalse */
if ($context === null && $type instanceof PackageInterface) {
$context = $type;
$type = 'package';
diff --git a/app/vendor/composer/composer/src/Composer/Question/StrictConfirmationQuestion.php b/app/vendor/composer/composer/src/Composer/Question/StrictConfirmationQuestion.php
index c27753b32..9cbc74ec5 100644
--- a/app/vendor/composer/composer/src/Composer/Question/StrictConfirmationQuestion.php
+++ b/app/vendor/composer/composer/src/Composer/Question/StrictConfirmationQuestion.php
@@ -40,7 +40,7 @@ class StrictConfirmationQuestion extends Question
*/
public function __construct(string $question, bool $default = true, string $trueAnswerRegex = '/^y(?:es)?$/i', string $falseAnswerRegex = '/^no?$/i')
{
- parent::__construct($question, (bool) $default);
+ parent::__construct($question, $default);
$this->trueAnswerRegex = $trueAnswerRegex;
$this->falseAnswerRegex = $falseAnswerRegex;
diff --git a/app/vendor/composer/composer/src/Composer/Repository/ArtifactRepository.php b/app/vendor/composer/composer/src/Composer/Repository/ArtifactRepository.php
index f73f4e9e1..78176fad7 100644
--- a/app/vendor/composer/composer/src/Composer/Repository/ArtifactRepository.php
+++ b/app/vendor/composer/composer/src/Composer/Repository/ArtifactRepository.php
@@ -129,7 +129,7 @@ private function getComposerInformation(\SplFileInfo $file): ?BasePackage
$package['dist'] = [
'type' => $fileType,
'url' => strtr($file->getPathname(), '\\', '/'),
- 'shasum' => sha1_file($file->getRealPath()),
+ 'shasum' => hash_file('sha1', $file->getRealPath()),
];
try {
diff --git a/app/vendor/composer/composer/src/Composer/Repository/ComposerRepository.php b/app/vendor/composer/composer/src/Composer/Repository/ComposerRepository.php
index ec244b129..7e4172b5a 100644
--- a/app/vendor/composer/composer/src/Composer/Repository/ComposerRepository.php
+++ b/app/vendor/composer/composer/src/Composer/Repository/ComposerRepository.php
@@ -432,8 +432,7 @@ private function getVendorNames(): array
$uniques = [];
foreach ($names as $name) {
- // @phpstan-ignore-next-line
- $uniques[substr($name, 0, strpos($name, '/'))] = true;
+ $uniques[explode('/', $name, 2)[0]] = true;
}
$vendors = array_keys($uniques);
@@ -828,7 +827,7 @@ private function hasProviders(): bool
/**
* @param string $name package name
* @param array|null $acceptableStabilities
- * @phpstan-param array|null $acceptableStabilities
+ * @phpstan-param array, BasePackage::STABILITY_*>|null $acceptableStabilities
* @param array|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value
* @phpstan-param array|null $stabilityFlags
* @param array> $alreadyLoaded
@@ -998,7 +997,7 @@ public function addPackage(PackageInterface $package)
* @param array $packageNames array of package name => ConstraintInterface|null - if a constraint is provided, only
* packages matching it will be loaded
* @param array|null $acceptableStabilities
- * @phpstan-param array|null $acceptableStabilities
+ * @phpstan-param array, BasePackage::STABILITY_*>|null $acceptableStabilities
* @param array|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value
* @phpstan-param array|null $stabilityFlags
* @param array> $alreadyLoaded
@@ -1130,7 +1129,7 @@ private function startCachedAsyncDownload(string $fileName, ?string $packageName
* @param string $name package name (must be lowercased already)
* @param array $versionData
* @param array|null $acceptableStabilities
- * @phpstan-param array|null $acceptableStabilities
+ * @phpstan-param array, BasePackage::STABILITY_*>|null $acceptableStabilities
* @param array|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value
* @phpstan-param array|null $stabilityFlags
*/
@@ -1448,7 +1447,7 @@ private function createPackages(array $packages, ?string $source = null): array
return $packageInstances;
} catch (\Exception $e) {
- throw new \RuntimeException('Could not load packages '.($packages[0]['name'] ?? json_encode($packages)).' in '.$this->getRepoName().($source ? ' from '.$source : '').': ['.get_class($e).'] '.$e->getMessage(), 0, $e);
+ throw new \RuntimeException('Could not load packages in '.$this->getRepoName().($source ? ' from '.$source : '').': ['.get_class($e).'] '.$e->getMessage(), 0, $e);
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Repository/FilesystemRepository.php b/app/vendor/composer/composer/src/Composer/Repository/FilesystemRepository.php
index ec37573f2..6ae6b149f 100644
--- a/app/vendor/composer/composer/src/Composer/Repository/FilesystemRepository.php
+++ b/app/vendor/composer/composer/src/Composer/Repository/FilesystemRepository.php
@@ -169,7 +169,26 @@ public function write(bool $devMode, InstallationManager $installationManager)
if ($installedVersionsClass !== false) {
$this->filesystem->filePutContentsIfModified($repoDir.'/InstalledVersions.php', $installedVersionsClass);
+ // make sure the in memory state is up to date with on disk
\Composer\InstalledVersions::reload($versions);
+
+ // make sure the selfDir matches the expected data at runtime if the class was loaded from the vendor dir, as it may have been
+ // loaded from the Composer sources, causing packages to appear twice in that case if the installed.php is loaded in addition to the
+ // in memory loaded data from above
+ try {
+ $reflProp = new \ReflectionProperty(\Composer\InstalledVersions::class, 'selfDir');
+ $reflProp->setAccessible(true);
+ $reflProp->setValue(null, strtr($repoDir, '\\', '/'));
+
+ $reflProp = new \ReflectionProperty(\Composer\InstalledVersions::class, 'installedIsLocalDir');
+ $reflProp->setAccessible(true);
+ $reflProp->setValue(null, true);
+ } catch (\ReflectionException $e) {
+ if (!Preg::isMatch('{Property .*? does not exist}i', $e->getMessage())) {
+ throw $e;
+ }
+ // noop, if outdated class is loaded we do not want to cause trouble
+ }
}
}
}
@@ -329,6 +348,14 @@ private function generateInstalledVersions(InstallationManager $installationMana
ksort($versions['versions']);
ksort($versions);
+ foreach ($versions['versions'] as $name => $version) {
+ foreach (['aliases', 'replaced', 'provided'] as $key) {
+ if (isset($versions['versions'][$name][$key])) {
+ sort($versions['versions'][$name][$key], SORT_NATURAL);
+ }
+ }
+ }
+
return $versions;
}
diff --git a/app/vendor/composer/composer/src/Composer/Repository/InstalledRepository.php b/app/vendor/composer/composer/src/Composer/Repository/InstalledRepository.php
index e3b52079e..3520fdec6 100644
--- a/app/vendor/composer/composer/src/Composer/Repository/InstalledRepository.php
+++ b/app/vendor/composer/composer/src/Composer/Repository/InstalledRepository.php
@@ -84,7 +84,7 @@ public function findPackagesWithReplacersAndProviders(string $name, $constraint
* @param string[] $packagesFound Used internally when recurring
*
* @return array[] An associative array of arrays as described above.
- * @phpstan-return array
+ * @phpstan-return array|false}>
*/
public function getDependents($needle, ?ConstraintInterface $constraint = null, bool $invert = false, bool $recurse = true, ?array $packagesFound = null): array
{
@@ -137,6 +137,7 @@ public function getDependents($needle, ?ConstraintInterface $constraint = null,
}
}
}
+ unset($needle);
}
// Require-dev is only relevant for the root package
@@ -163,7 +164,7 @@ public function getDependents($needle, ?ConstraintInterface $constraint = null,
}
// When inverting, we need to check for conflicts of the needles against installed packages
- if ($invert && in_array($package->getName(), $needles)) {
+ if ($invert && in_array($package->getName(), $needles, true)) {
foreach ($package->getConflicts() as $link) {
foreach ($this->findPackages($link->getTarget()) as $pkg) {
$version = new Constraint('=', $pkg->getVersion());
@@ -176,7 +177,7 @@ public function getDependents($needle, ?ConstraintInterface $constraint = null,
// List conflicts against X as they may explain why the current version was selected, or explain why it is rejected if the conflict matched when inverting
foreach ($package->getConflicts() as $link) {
- if (in_array($link->getTarget(), $needles)) {
+ if (in_array($link->getTarget(), $needles, true)) {
foreach ($this->findPackages($link->getTarget()) as $pkg) {
$version = new Constraint('=', $pkg->getVersion());
if ($link->getConstraint()->matches($version) === $invert) {
@@ -187,7 +188,7 @@ public function getDependents($needle, ?ConstraintInterface $constraint = null,
}
// When inverting, we need to check for conflicts of the needles' requirements against installed packages
- if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
+ if ($invert && $constraint && in_array($package->getName(), $needles, true) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
foreach ($package->getRequires() as $link) {
if (PlatformRepository::isPlatformPackage($link->getTarget())) {
if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
diff --git a/app/vendor/composer/composer/src/Composer/Repository/PathRepository.php b/app/vendor/composer/composer/src/Composer/Repository/PathRepository.php
index 06676e73e..0b8d99236 100644
--- a/app/vendor/composer/composer/src/Composer/Repository/PathRepository.php
+++ b/app/vendor/composer/composer/src/Composer/Repository/PathRepository.php
@@ -116,7 +116,7 @@ public function __construct(array $repoConfig, IOInterface $io, Config $config,
$this->loader = new ArrayLoader(null, true);
$this->url = Platform::expandPath($repoConfig['url']);
$this->process = $process ?? new ProcessExecutor($io);
- $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
+ $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser(), $io);
$this->repoConfig = $repoConfig;
$this->options = $repoConfig['options'] ?? [];
if (!isset($this->options['relative'])) {
@@ -181,7 +181,7 @@ protected function initialize(): void
if ('none' === $reference) {
$package['dist']['reference'] = null;
} elseif ('config' === $reference || 'auto' === $reference) {
- $package['dist']['reference'] = sha1($json . serialize($this->options));
+ $package['dist']['reference'] = hash('sha1', $json . serialize($this->options));
}
// copy symlink/relative options to transport options
@@ -194,16 +194,16 @@ protected function initialize(): void
// carry over the root package version if this path repo is in the same git repository as root package
if (!isset($package['version']) && ($rootVersion = Platform::getEnv('COMPOSER_ROOT_VERSION'))) {
if (
- 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
- && 0 === $this->process->execute('git rev-parse HEAD', $ref2)
+ 0 === $this->process->execute(['git', 'rev-parse', 'HEAD'], $ref1, $path)
+ && 0 === $this->process->execute(['git', 'rev-parse', 'HEAD'], $ref2)
&& $ref1 === $ref2
) {
- $package['version'] = $rootVersion;
+ $package['version'] = $this->versionGuesser->getRootVersionFromEnv();
}
}
$output = '';
- if ('auto' === $reference && is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H'.GitUtil::getNoShowSignatureFlag($this->process), $output, $path)) {
+ if ('auto' === $reference && is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute(array_merge(['git', 'log', '-n1', '--pretty=%H'], GitUtil::getNoShowSignatureFlags($this->process)), $output, $path)) {
$package['dist']['reference'] = trim($output);
}
diff --git a/app/vendor/composer/composer/src/Composer/Repository/PlatformRepository.php b/app/vendor/composer/composer/src/Composer/Repository/PlatformRepository.php
index 61c70cf32..4c6024946 100644
--- a/app/vendor/composer/composer/src/Composer/Repository/PlatformRepository.php
+++ b/app/vendor/composer/composer/src/Composer/Repository/PlatformRepository.php
@@ -110,6 +110,8 @@ protected function initialize(): void
{
parent::initialize();
+ $libraries = [];
+
$this->versionParser = new VersionParser();
// Add each of the override versions as options.
@@ -207,12 +209,12 @@ protected function initialize(): void
// librabbitmq version => 0.9.0
if (Preg::isMatch('/^librabbitmq version => (?.+)$/im', $info, $librabbitmqMatches)) {
- $this->addLibrary($name.'-librabbitmq', $librabbitmqMatches['version'], 'AMQP librabbitmq version');
+ $this->addLibrary($libraries, $name.'-librabbitmq', $librabbitmqMatches['version'], 'AMQP librabbitmq version');
}
// AMQP protocol version => 0-9-1
if (Preg::isMatchStrictGroups('/^AMQP protocol version => (?.+)$/im', $info, $protocolMatches)) {
- $this->addLibrary($name.'-protocol', str_replace('-', '.', $protocolMatches['version']), 'AMQP protocol version');
+ $this->addLibrary($libraries, $name.'-protocol', str_replace('-', '.', $protocolMatches['version']), 'AMQP protocol version');
}
break;
@@ -221,13 +223,13 @@ protected function initialize(): void
// BZip2 Version => 1.0.6, 6-Sept-2010
if (Preg::isMatch('/^BZip2 Version => (?.*),/im', $info, $matches)) {
- $this->addLibrary($name, $matches['version']);
+ $this->addLibrary($libraries, $name, $matches['version']);
}
break;
case 'curl':
$curlVersion = $this->runtime->invoke('curl_version');
- $this->addLibrary($name, $curlVersion['version']);
+ $this->addLibrary($libraries, $name, $curlVersion['version']);
$info = $this->runtime->getExtensionInfo($name);
@@ -236,25 +238,25 @@ protected function initialize(): void
$library = strtolower($sslMatches['library']);
if ($library === 'openssl') {
$parsedVersion = Version::parseOpenssl($sslMatches['version'], $isFips);
- $this->addLibrary($name.'-openssl'.($isFips ? '-fips' : ''), $parsedVersion, 'curl OpenSSL version ('.$parsedVersion.')', [], $isFips ? ['curl-openssl'] : []);
+ $this->addLibrary($libraries, $name.'-openssl'.($isFips ? '-fips' : ''), $parsedVersion, 'curl OpenSSL version ('.$parsedVersion.')', [], $isFips ? ['curl-openssl'] : []);
} else {
if ($library === '(securetransport) openssl') {
$shortlib = 'securetransport';
} else {
$shortlib = $library;
}
- $this->addLibrary($name.'-'.$shortlib, $sslMatches['version'], 'curl '.$library.' version ('.$sslMatches['version'].')', ['curl-openssl']);
+ $this->addLibrary($libraries, $name.'-'.$shortlib, $sslMatches['version'], 'curl '.$library.' version ('.$sslMatches['version'].')', ['curl-openssl']);
}
}
// libSSH Version => libssh2/1.4.3
if (Preg::isMatchStrictGroups('{^libSSH Version => (?[^/]+)/(?.+?)(?:/.*)?$}im', $info, $sshMatches)) {
- $this->addLibrary($name.'-'.strtolower($sshMatches['library']), $sshMatches['version'], 'curl '.$sshMatches['library'].' version');
+ $this->addLibrary($libraries, $name.'-'.strtolower($sshMatches['library']), $sshMatches['version'], 'curl '.$sshMatches['library'].' version');
}
// ZLib Version => 1.2.8
if (Preg::isMatchStrictGroups('{^ZLib Version => (?.+)$}im', $info, $zlibMatches)) {
- $this->addLibrary($name.'-zlib', $zlibMatches['version'], 'curl zlib version');
+ $this->addLibrary($libraries, $name.'-zlib', $zlibMatches['version'], 'curl zlib version');
}
break;
@@ -263,7 +265,7 @@ protected function initialize(): void
// timelib version => 2018.03
if (Preg::isMatchStrictGroups('/^timelib version => (?.+)$/im', $info, $timelibMatches)) {
- $this->addLibrary($name.'-timelib', $timelibMatches['version'], 'date timelib version');
+ $this->addLibrary($libraries, $name.'-timelib', $timelibMatches['version'], 'date timelib version');
}
// Timezone Database => internal
@@ -272,9 +274,9 @@ protected function initialize(): void
if (Preg::isMatchStrictGroups('/^"Olson" Timezone Database Version => (?.+?)(?:\.system)?$/im', $info, $zoneinfoMatches)) {
// If the timezonedb is provided by ext/timezonedb, register that version as a replacement
if ($external && in_array('timezonedb', $loadedExtensions, true)) {
- $this->addLibrary('timezonedb-zoneinfo', $zoneinfoMatches['version'], 'zoneinfo ("Olson") database for date (replaced by timezonedb)', [$name.'-zoneinfo']);
+ $this->addLibrary($libraries, 'timezonedb-zoneinfo', $zoneinfoMatches['version'], 'zoneinfo ("Olson") database for date (replaced by timezonedb)', [$name.'-zoneinfo']);
} else {
- $this->addLibrary($name.'-zoneinfo', $zoneinfoMatches['version'], 'zoneinfo ("Olson") database for date');
+ $this->addLibrary($libraries, $name.'-zoneinfo', $zoneinfoMatches['version'], 'zoneinfo ("Olson") database for date');
}
}
}
@@ -285,39 +287,39 @@ protected function initialize(): void
// libmagic => 537
if (Preg::isMatch('/^libmagic => (?.+)$/im', $info, $magicMatches)) {
- $this->addLibrary($name.'-libmagic', $magicMatches['version'], 'fileinfo libmagic version');
+ $this->addLibrary($libraries, $name.'-libmagic', $magicMatches['version'], 'fileinfo libmagic version');
}
break;
case 'gd':
- $this->addLibrary($name, $this->runtime->getConstant('GD_VERSION'));
+ $this->addLibrary($libraries, $name, $this->runtime->getConstant('GD_VERSION'));
$info = $this->runtime->getExtensionInfo($name);
if (Preg::isMatchStrictGroups('/^libJPEG Version => (?.+?)(?: compatible)?$/im', $info, $libjpegMatches)) {
- $this->addLibrary($name.'-libjpeg', Version::parseLibjpeg($libjpegMatches['version']), 'libjpeg version for gd');
+ $this->addLibrary($libraries, $name.'-libjpeg', Version::parseLibjpeg($libjpegMatches['version']), 'libjpeg version for gd');
}
if (Preg::isMatchStrictGroups('/^libPNG Version => (?.+)$/im', $info, $libpngMatches)) {
- $this->addLibrary($name.'-libpng', $libpngMatches['version'], 'libpng version for gd');
+ $this->addLibrary($libraries, $name.'-libpng', $libpngMatches['version'], 'libpng version for gd');
}
if (Preg::isMatchStrictGroups('/^FreeType Version => (?.+)$/im', $info, $freetypeMatches)) {
- $this->addLibrary($name.'-freetype', $freetypeMatches['version'], 'freetype version for gd');
+ $this->addLibrary($libraries, $name.'-freetype', $freetypeMatches['version'], 'freetype version for gd');
}
if (Preg::isMatchStrictGroups('/^libXpm Version => (?\d+)$/im', $info, $libxpmMatches)) {
- $this->addLibrary($name.'-libxpm', Version::convertLibxpmVersionId((int) $libxpmMatches['versionId']), 'libxpm version for gd');
+ $this->addLibrary($libraries, $name.'-libxpm', Version::convertLibxpmVersionId((int) $libxpmMatches['versionId']), 'libxpm version for gd');
}
break;
case 'gmp':
- $this->addLibrary($name, $this->runtime->getConstant('GMP_VERSION'));
+ $this->addLibrary($libraries, $name, $this->runtime->getConstant('GMP_VERSION'));
break;
case 'iconv':
- $this->addLibrary($name, $this->runtime->getConstant('ICONV_VERSION'));
+ $this->addLibrary($libraries, $name, $this->runtime->getConstant('ICONV_VERSION'));
break;
case 'intl':
@@ -326,47 +328,49 @@ protected function initialize(): void
$description = 'The ICU unicode and globalization support library';
// Truthy check is for testing only so we can make the condition fail
if ($this->runtime->hasConstant('INTL_ICU_VERSION')) {
- $this->addLibrary('icu', $this->runtime->getConstant('INTL_ICU_VERSION'), $description);
+ $this->addLibrary($libraries, 'icu', $this->runtime->getConstant('INTL_ICU_VERSION'), $description);
} elseif (Preg::isMatch('/^ICU version => (?.+)$/im', $info, $matches)) {
- $this->addLibrary('icu', $matches['version'], $description);
+ $this->addLibrary($libraries, 'icu', $matches['version'], $description);
}
// ICU TZData version => 2019c
if (Preg::isMatchStrictGroups('/^ICU TZData version => (?.*)$/im', $info, $zoneinfoMatches) && null !== ($version = Version::parseZoneinfoVersion($zoneinfoMatches['version']))) {
- $this->addLibrary('icu-zoneinfo', $version, 'zoneinfo ("Olson") database for icu');
+ $this->addLibrary($libraries, 'icu-zoneinfo', $version, 'zoneinfo ("Olson") database for icu');
}
// Add a separate version for the CLDR library version
if ($this->runtime->hasClass('ResourceBundle')) {
$resourceBundle = $this->runtime->invoke(['ResourceBundle', 'create'], ['root', 'ICUDATA', false]);
if ($resourceBundle !== null) {
- $this->addLibrary('icu-cldr', $resourceBundle->get('Version'), 'ICU CLDR project version');
+ $this->addLibrary($libraries, 'icu-cldr', $resourceBundle->get('Version'), 'ICU CLDR project version');
}
}
if ($this->runtime->hasClass('IntlChar')) {
- $this->addLibrary('icu-unicode', implode('.', array_slice($this->runtime->invoke(['IntlChar', 'getUnicodeVersion']), 0, 3)), 'ICU unicode version');
+ $this->addLibrary($libraries, 'icu-unicode', implode('.', array_slice($this->runtime->invoke(['IntlChar', 'getUnicodeVersion']), 0, 3)), 'ICU unicode version');
}
break;
case 'imagick':
+ // @phpstan-ignore staticMethod.dynamicCall (called like this for mockability)
$imageMagickVersion = $this->runtime->construct('Imagick')->getVersion();
// 6.x: ImageMagick 6.2.9 08/24/06 Q16 http://www.imagemagick.org
// 7.x: ImageMagick 7.0.8-34 Q16 x86_64 2019-03-23 https://imagemagick.org
- Preg::match('/^ImageMagick (?[\d.]+)(?:-(?\d+))?/', $imageMagickVersion['versionString'], $matches);
- $version = $matches['version'];
- if (isset($matches['patch'])) {
- $version .= '.'.$matches['patch'];
- }
+ if (Preg::isMatch('/^ImageMagick (?[\d.]+)(?:-(?\d+))?/', $imageMagickVersion['versionString'], $matches)) {
+ $version = $matches['version'];
+ if (isset($matches['patch'])) {
+ $version .= '.'.$matches['patch'];
+ }
- $this->addLibrary($name.'-imagemagick', $version, null, ['imagick']);
+ $this->addLibrary($libraries, $name.'-imagemagick', $version, null, ['imagick']);
+ }
break;
case 'ldap':
$info = $this->runtime->getExtensionInfo($name);
if (Preg::isMatchStrictGroups('/^Vendor Version => (?\d+)$/im', $info, $matches) && Preg::isMatchStrictGroups('/^Vendor Name => (?.+)$/im', $info, $vendorMatches)) {
- $this->addLibrary($name.'-'.strtolower($vendorMatches['vendor']), Version::convertOpenldapVersionId((int) $matches['versionId']), $vendorMatches['vendor'].' version of ldap');
+ $this->addLibrary($libraries, $name.'-'.strtolower($vendorMatches['vendor']), Version::convertOpenldapVersionId((int) $matches['versionId']), $vendorMatches['vendor'].' version of ldap');
}
break;
@@ -375,7 +379,7 @@ protected function initialize(): void
$libxmlProvides = array_map(static function ($extension): string {
return $extension . '-libxml';
}, array_intersect($loadedExtensions, ['dom', 'simplexml', 'xml', 'xmlreader', 'xmlwriter']));
- $this->addLibrary($name, $this->runtime->getConstant('LIBXML_DOTTED_VERSION'), 'libxml library version', [], $libxmlProvides);
+ $this->addLibrary($libraries, $name, $this->runtime->getConstant('LIBXML_DOTTED_VERSION'), 'libxml library version', [], $libxmlProvides);
break;
@@ -384,16 +388,16 @@ protected function initialize(): void
// libmbfl version => 1.3.2
if (Preg::isMatch('/^libmbfl version => (?.+)$/im', $info, $libmbflMatches)) {
- $this->addLibrary($name.'-libmbfl', $libmbflMatches['version'], 'mbstring libmbfl version');
+ $this->addLibrary($libraries, $name.'-libmbfl', $libmbflMatches['version'], 'mbstring libmbfl version');
}
if ($this->runtime->hasConstant('MB_ONIGURUMA_VERSION')) {
- $this->addLibrary($name.'-oniguruma', $this->runtime->getConstant('MB_ONIGURUMA_VERSION'), 'mbstring oniguruma version');
+ $this->addLibrary($libraries, $name.'-oniguruma', $this->runtime->getConstant('MB_ONIGURUMA_VERSION'), 'mbstring oniguruma version');
// Multibyte regex (oniguruma) version => 5.9.5
// oniguruma version => 6.9.0
} elseif (Preg::isMatch('/^(?:oniguruma|Multibyte regex \(oniguruma\)) version => (?.+)$/im', $info, $onigurumaMatches)) {
- $this->addLibrary($name.'-oniguruma', $onigurumaMatches['version'], 'mbstring oniguruma version');
+ $this->addLibrary($libraries, $name.'-oniguruma', $onigurumaMatches['version'], 'mbstring oniguruma version');
}
break;
@@ -403,7 +407,7 @@ protected function initialize(): void
// libmemcached version => 1.0.18
if (Preg::isMatch('/^libmemcached version => (?.+)$/im', $info, $matches)) {
- $this->addLibrary($name.'-libmemcached', $matches['version'], 'libmemcached version');
+ $this->addLibrary($libraries, $name.'-libmemcached', $matches['version'], 'libmemcached version');
}
break;
@@ -411,18 +415,18 @@ protected function initialize(): void
// OpenSSL 1.1.1g 21 Apr 2020
if (Preg::isMatchStrictGroups('{^(?:OpenSSL|LibreSSL)?\s*(?\S+)}i', $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), $matches)) {
$parsedVersion = Version::parseOpenssl($matches['version'], $isFips);
- $this->addLibrary($name.($isFips ? '-fips' : ''), $parsedVersion, $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), [], $isFips ? [$name] : []);
+ $this->addLibrary($libraries, $name.($isFips ? '-fips' : ''), $parsedVersion, $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), [], $isFips ? [$name] : []);
}
break;
case 'pcre':
- $this->addLibrary($name, Preg::replace('{^(\S+).*}', '$1', $this->runtime->getConstant('PCRE_VERSION')));
+ $this->addLibrary($libraries, $name, Preg::replace('{^(\S+).*}', '$1', $this->runtime->getConstant('PCRE_VERSION')));
$info = $this->runtime->getExtensionInfo($name);
// PCRE Unicode Version => 12.1.0
if (Preg::isMatchStrictGroups('/^PCRE Unicode Version => (?.+)$/im', $info, $pcreUnicodeMatches)) {
- $this->addLibrary($name.'-unicode', $pcreUnicodeMatches['version'], 'PCRE Unicode version support');
+ $this->addLibrary($libraries, $name.'-unicode', $pcreUnicodeMatches['version'], 'PCRE Unicode version support');
}
break;
@@ -432,7 +436,7 @@ protected function initialize(): void
$info = $this->runtime->getExtensionInfo($name);
if (Preg::isMatchStrictGroups('/^(?:Client API version|Version) => mysqlnd (?.+?) /mi', $info, $matches)) {
- $this->addLibrary($name.'-mysqlnd', $matches['version'], 'mysqlnd library version for '.$name);
+ $this->addLibrary($libraries, $name.'-mysqlnd', $matches['version'], 'mysqlnd library version for '.$name);
}
break;
@@ -440,17 +444,17 @@ protected function initialize(): void
$info = $this->runtime->getExtensionInfo($name);
if (Preg::isMatchStrictGroups('/^libmongoc bundled version => (?.+)$/im', $info, $libmongocMatches)) {
- $this->addLibrary($name.'-libmongoc', $libmongocMatches['version'], 'libmongoc version of mongodb');
+ $this->addLibrary($libraries, $name.'-libmongoc', $libmongocMatches['version'], 'libmongoc version of mongodb');
}
if (Preg::isMatchStrictGroups('/^libbson bundled version => (?.+)$/im', $info, $libbsonMatches)) {
- $this->addLibrary($name.'-libbson', $libbsonMatches['version'], 'libbson version of mongodb');
+ $this->addLibrary($libraries, $name.'-libbson', $libbsonMatches['version'], 'libbson version of mongodb');
}
break;
case 'pgsql':
if ($this->runtime->hasConstant('PGSQL_LIBPQ_VERSION')) {
- $this->addLibrary('pgsql-libpq', $this->runtime->getConstant('PGSQL_LIBPQ_VERSION'), 'libpq for pgsql');
+ $this->addLibrary($libraries, 'pgsql-libpq', $this->runtime->getConstant('PGSQL_LIBPQ_VERSION'), 'libpq for pgsql');
break;
}
// intentional fall-through to next case...
@@ -459,7 +463,7 @@ protected function initialize(): void
$info = $this->runtime->getExtensionInfo($name);
if (Preg::isMatch('/^PostgreSQL\(libpq\) Version => (?.*)$/im', $info, $matches)) {
- $this->addLibrary($name.'-libpq', $matches['version'], 'libpq for '.$name);
+ $this->addLibrary($libraries, $name.'-libpq', $matches['version'], 'libpq for '.$name);
}
break;
@@ -469,7 +473,7 @@ protected function initialize(): void
// Used Library => Compiled => Linked
// libpq => 14.3 (Ubuntu 14.3-1.pgdg22.04+1) => 15.0.2
if (Preg::isMatch('/^libpq => (?.+) => (?.+)$/im', $info, $matches)) {
- $this->addLibrary($name.'-libpq', $matches['linked'], 'libpq for '.$name);
+ $this->addLibrary($libraries, $name.'-libpq', $matches['linked'], 'libpq for '.$name);
}
break;
@@ -485,14 +489,15 @@ protected function initialize(): void
* pre-release ID in practice is always 0xff even for RCs etc, so we ignore it
*/
$libRdKafkaVersionInt = $this->runtime->getConstant('RD_KAFKA_VERSION');
- $this->addLibrary($name.'-librdkafka', sprintf('%d.%d.%d', ($libRdKafkaVersionInt & 0xFF000000) >> 24, ($libRdKafkaVersionInt & 0x00FF0000) >> 16, ($libRdKafkaVersionInt & 0x0000FF00) >> 8), 'librdkafka for '.$name);
+ $this->addLibrary($libraries, $name.'-librdkafka', sprintf('%d.%d.%d', ($libRdKafkaVersionInt & 0x7F000000) >> 24, ($libRdKafkaVersionInt & 0x00FF0000) >> 16, ($libRdKafkaVersionInt & 0x0000FF00) >> 8), 'librdkafka for '.$name);
}
break;
case 'libsodium':
case 'sodium':
if ($this->runtime->hasConstant('SODIUM_LIBRARY_VERSION')) {
- $this->addLibrary('libsodium', $this->runtime->getConstant('SODIUM_LIBRARY_VERSION'));
+ $this->addLibrary($libraries, 'libsodium', $this->runtime->getConstant('SODIUM_LIBRARY_VERSION'));
+ $this->addLibrary($libraries, 'libsodium', $this->runtime->getConstant('SODIUM_LIBRARY_VERSION'));
}
break;
@@ -501,7 +506,7 @@ protected function initialize(): void
$info = $this->runtime->getExtensionInfo($name);
if (Preg::isMatch('/^SQLite Library => (?.+)$/im', $info, $matches)) {
- $this->addLibrary($name.'-sqlite', $matches['version']);
+ $this->addLibrary($libraries, $name.'-sqlite', $matches['version']);
}
break;
@@ -509,16 +514,16 @@ protected function initialize(): void
$info = $this->runtime->getExtensionInfo($name);
if (Preg::isMatch('/^libssh2 version => (?.+)$/im', $info, $matches)) {
- $this->addLibrary($name.'-libssh2', $matches['version']);
+ $this->addLibrary($libraries, $name.'-libssh2', $matches['version']);
}
break;
case 'xsl':
- $this->addLibrary('libxslt', $this->runtime->getConstant('LIBXSLT_DOTTED_VERSION'), null, ['xsl']);
+ $this->addLibrary($libraries, 'libxslt', $this->runtime->getConstant('LIBXSLT_DOTTED_VERSION'), null, ['xsl']);
$info = $this->runtime->getExtensionInfo('xsl');
if (Preg::isMatch('/^libxslt compiled against libxml Version => (?.+)$/im', $info, $matches)) {
- $this->addLibrary('libxslt-libxml', $matches['version'], 'libxml version libxslt is compiled against');
+ $this->addLibrary($libraries, 'libxslt-libxml', $matches['version'], 'libxml version libxslt is compiled against');
}
break;
@@ -526,23 +531,23 @@ protected function initialize(): void
$info = $this->runtime->getExtensionInfo('yaml');
if (Preg::isMatch('/^LibYAML Version => (?.+)$/im', $info, $matches)) {
- $this->addLibrary($name.'-libyaml', $matches['version'], 'libyaml version of yaml');
+ $this->addLibrary($libraries, $name.'-libyaml', $matches['version'], 'libyaml version of yaml');
}
break;
case 'zip':
if ($this->runtime->hasConstant('LIBZIP_VERSION', 'ZipArchive')) {
- $this->addLibrary($name.'-libzip', $this->runtime->getConstant('LIBZIP_VERSION', 'ZipArchive'), null, ['zip']);
+ $this->addLibrary($libraries, $name.'-libzip', $this->runtime->getConstant('LIBZIP_VERSION', 'ZipArchive'), null, ['zip']);
}
break;
case 'zlib':
if ($this->runtime->hasConstant('ZLIB_VERSION')) {
- $this->addLibrary($name, $this->runtime->getConstant('ZLIB_VERSION'));
+ $this->addLibrary($libraries, $name, $this->runtime->getConstant('ZLIB_VERSION'));
// Linked Version => 1.2.8
} elseif (Preg::isMatch('/^Linked Version => (?.+)$/im', $this->runtime->getExtensionInfo($name), $matches)) {
- $this->addLibrary($name, $matches['version']);
+ $this->addLibrary($libraries, $name, $matches['version']);
}
break;
@@ -678,10 +683,11 @@ private function buildPackageName(string $name): string
}
/**
- * @param string[] $replaces
- * @param string[] $provides
+ * @param array $libraries
+ * @param array