diff --git a/composer.lock b/composer.lock index 019b129b5..7bccf2d7b 100644 --- a/composer.lock +++ b/composer.lock @@ -226,26 +226,26 @@ }, { "name": "composer/pcre", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "0e455b78ac53637929b29d5ab5bf3c978329c1eb" + "reference": "06d0e49d6e136e4521c6bad18598bf0f6062ae37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/0e455b78ac53637929b29d5ab5bf3c978329c1eb", - "reference": "0e455b78ac53637929b29d5ab5bf3c978329c1eb", + "url": "https://api.github.com/repos/composer/pcre/zipball/06d0e49d6e136e4521c6bad18598bf0f6062ae37", + "reference": "06d0e49d6e136e4521c6bad18598bf0f6062ae37", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "conflict": { - "phpstan/phpstan": "<1.11.8" + "phpstan/phpstan": "<1.11.10" }, "require-dev": { - "phpstan/phpstan": "^1.11.8", + "phpstan/phpstan": "^1.11.10", "phpstan/phpstan-strict-rules": "^1.1", "phpunit/phpunit": "^8 || ^9" }, @@ -285,7 +285,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/2.2.0" + "source": "https://github.com/composer/pcre/tree/2.3.0" }, "funding": [ { @@ -301,7 +301,7 @@ "type": "tidelift" } ], - "time": "2024-07-25T09:28:32+00:00" + "time": "2024-08-19T19:14:31+00:00" }, { "name": "composer/semver", @@ -941,16 +941,16 @@ }, { "name": "symfony/console", - "version": "v5.4.41", + "version": "v5.4.42", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6473d441a913cb997123b59ff2dbe3d1cf9e11ba" + "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6473d441a913cb997123b59ff2dbe3d1cf9e11ba", - "reference": "6473d441a913cb997123b59ff2dbe3d1cf9e11ba", + "url": "https://api.github.com/repos/symfony/console/zipball/cef62396a0477e94fc52e87a17c6e5c32e226b7f", + "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f", "shasum": "" }, "require": { @@ -1020,7 +1020,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.41" + "source": "https://github.com/symfony/console/tree/v5.4.42" }, "funding": [ { @@ -1036,7 +1036,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T07:48:55+00:00" + "time": "2024-07-26T12:21:55+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1174,16 +1174,16 @@ }, { "name": "symfony/finder", - "version": "v5.4.40", + "version": "v5.4.42", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "f51cff4687547641c7d8180d74932ab40b2205ce" + "reference": "0724c51fa067b198e36506d2864e09a52180998a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/f51cff4687547641c7d8180d74932ab40b2205ce", - "reference": "f51cff4687547641c7d8180d74932ab40b2205ce", + "url": "https://api.github.com/repos/symfony/finder/zipball/0724c51fa067b198e36506d2864e09a52180998a", + "reference": "0724c51fa067b198e36506d2864e09a52180998a", "shasum": "" }, "require": { @@ -1217,7 +1217,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.40" + "source": "https://github.com/symfony/finder/tree/v5.4.42" }, "funding": [ { @@ -1233,7 +1233,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:33:22+00:00" + "time": "2024-07-22T08:53:29+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1932,16 +1932,16 @@ }, { "name": "symfony/string", - "version": "v5.4.41", + "version": "v5.4.42", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "065a9611e0b1fd2197a867e1fb7f2238191b7096" + "reference": "909cec913edea162a3b2836788228ad45fcab337" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/065a9611e0b1fd2197a867e1fb7f2238191b7096", - "reference": "065a9611e0b1fd2197a867e1fb7f2238191b7096", + "url": "https://api.github.com/repos/symfony/string/zipball/909cec913edea162a3b2836788228ad45fcab337", + "reference": "909cec913edea162a3b2836788228ad45fcab337", "shasum": "" }, "require": { @@ -1998,7 +1998,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.41" + "source": "https://github.com/symfony/string/tree/v5.4.42" }, "funding": [ { @@ -2014,22 +2014,22 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:20:55+00:00" + "time": "2024-07-20T18:38:32+00:00" } ], "packages-dev": [ { "name": "phpstan/phpstan", - "version": "1.11.8", + "version": "1.11.11", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec" + "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec", - "reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/707c2aed5d8d0075666e673a5e71440c1d01a5a3", + "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3", "shasum": "" }, "require": { @@ -2074,7 +2074,7 @@ "type": "github" } ], - "time": "2024-07-24T07:01:22+00:00" + "time": "2024-08-19T14:37:29+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -2226,16 +2226,16 @@ }, { "name": "phpstan/phpstan-symfony", - "version": "1.4.6", + "version": "1.4.8", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-symfony.git", - "reference": "e909a075d69e0d4db262ac3407350ae2c6b6ab5f" + "reference": "14eec8c011b856eee4d744a2a3f709db1e1858bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/e909a075d69e0d4db262ac3407350ae2c6b6ab5f", - "reference": "e909a075d69e0d4db262ac3407350ae2c6b6ab5f", + "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/14eec8c011b856eee4d744a2a3f709db1e1858bd", + "reference": "14eec8c011b856eee4d744a2a3f709db1e1858bd", "shasum": "" }, "require": { @@ -2292,22 +2292,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.4.6" + "source": "https://github.com/phpstan/phpstan-symfony/tree/1.4.8" }, - "time": "2024-07-16T11:48:54+00:00" + "time": "2024-08-13T19:43:40+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v7.1.2", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "8eb63f1c0e2001f97b3cd9ed550b18765cdeb1c8" + "reference": "e823122d31935eb711e2767c31f3d71cb0b87fb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/8eb63f1c0e2001f97b3cd9ed550b18765cdeb1c8", - "reference": "8eb63f1c0e2001f97b3cd9ed550b18765cdeb1c8", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/e823122d31935eb711e2767c31f3d71cb0b87fb1", + "reference": "e823122d31935eb711e2767c31f3d71cb0b87fb1", "shasum": "" }, "require": { @@ -2360,7 +2360,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.1.2" + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.1.3" }, "funding": [ { @@ -2376,7 +2376,7 @@ "type": "tidelift" } ], - "time": "2024-06-25T19:55:06+00:00" + "time": "2024-07-26T12:41:01+00:00" } ], "aliases": [], diff --git a/phpstan/baseline-8.3.neon b/phpstan/baseline-8.3.neon index 5e17a28f4..4871d6cf6 100644 --- a/phpstan/baseline-8.3.neon +++ b/phpstan/baseline-8.3.neon @@ -105,16 +105,6 @@ parameters: count: 1 path: ../src/Composer/EventDispatcher/EventDispatcher.php - - - message: "#^Parameter \\#1 \\$stream of function fwrite expects resource, resource\\|false given\\.$#" - count: 1 - path: ../src/Composer/IO/BufferIO.php - - - - message: "#^Parameter \\#1 \\$stream of function rewind expects resource, resource\\|false given\\.$#" - count: 1 - path: ../src/Composer/IO/BufferIO.php - - message: "#^Parameter \\#1 \\$stream of function fclose expects resource, resource\\|false given\\.$#" count: 1 diff --git a/phpstan/baseline.neon b/phpstan/baseline.neon index 7d3160d1c..8bf450f15 100644 --- a/phpstan/baseline.neon +++ b/phpstan/baseline.neon @@ -1885,11 +1885,6 @@ parameters: count: 1 path: ../src/Composer/EventDispatcher/EventDispatcher.php - - - message: "#^Only booleans are allowed in an if condition, array\\ given\\.$#" - count: 1 - path: ../src/Composer/EventDispatcher/EventDispatcher.php - - message: "#^Only booleans are allowed in an if condition, string\\|false given\\.$#" count: 2 @@ -1985,46 +1980,6 @@ parameters: count: 1 path: ../src/Composer/IO/BaseIO.php - - - message: "#^Only booleans are allowed in a ternary operator condition, Symfony\\\\Component\\\\Console\\\\Formatter\\\\OutputFormatterInterface\\|null given\\.$#" - count: 1 - path: ../src/Composer/IO/BufferIO.php - - - - message: "#^PHPDoc type Symfony\\\\Component\\\\Console\\\\Input\\\\StringInput of property Composer\\\\IO\\\\BufferIO\\:\\:\\$input is not the same as PHPDoc type Symfony\\\\Component\\\\Console\\\\Input\\\\InputInterface of overridden property Composer\\\\IO\\\\ConsoleIO\\:\\:\\$input\\.$#" - count: 1 - path: ../src/Composer/IO/BufferIO.php - - - - message: "#^PHPDoc type Symfony\\\\Component\\\\Console\\\\Output\\\\StreamOutput of property Composer\\\\IO\\\\BufferIO\\:\\:\\$output is not the same as PHPDoc type Symfony\\\\Component\\\\Console\\\\Output\\\\OutputInterface of overridden property Composer\\\\IO\\\\ConsoleIO\\:\\:\\$output\\.$#" - count: 1 - path: ../src/Composer/IO/BufferIO.php - - - - message: "#^Parameter \\#1 \\$fp of function fwrite expects resource, resource\\|false given\\.$#" - count: 1 - path: ../src/Composer/IO/BufferIO.php - - - - message: "#^Parameter \\#1 \\$fp of function rewind expects resource, resource\\|false given\\.$#" - count: 1 - path: ../src/Composer/IO/BufferIO.php - - - - message: "#^Parameter \\#1 \\$stream of class Symfony\\\\Component\\\\Console\\\\Output\\\\StreamOutput constructor expects resource, resource\\|false given\\.$#" - count: 1 - path: ../src/Composer/IO/BufferIO.php - - - - message: "#^Parameter \\#1 \\$stream of method Symfony\\\\Component\\\\Console\\\\Input\\\\Input\\:\\:setStream\\(\\) expects resource, resource\\|false given\\.$#" - count: 1 - path: ../src/Composer/IO/BufferIO.php - - - - message: "#^Parameter \\#3 \\$subject of static method Composer\\\\Pcre\\\\Preg\\:\\:replaceCallback\\(\\) expects string, string\\|false given\\.$#" - count: 1 - path: ../src/Composer/IO/BufferIO.php - - message: "#^Parameter \\#1 \\$attempts of method Symfony\\\\Component\\\\Console\\\\Question\\\\Question\\:\\:setMaxAttempts\\(\\) expects int\\|null, int\\\\|int\\<1, max\\>\\|true\\|null given\\.$#" count: 1 @@ -2145,71 +2100,6 @@ parameters: count: 1 path: ../src/Composer/Installer/BinaryInstaller.php - - - message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" - count: 2 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 1 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Foreach overwrites \\$batch with its value variable\\.$#" - count: 2 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Only booleans are allowed in &&, Composer\\\\EventDispatcher\\\\EventDispatcher\\|null given on the right side\\.$#" - count: 2 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Only booleans are allowed in &&, array given on the right side\\.$#" - count: 1 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Only booleans are allowed in a negated boolean, string\\|false given\\.$#" - count: 1 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Only booleans are allowed in a negated boolean, string\\|null given\\.$#" - count: 1 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Only booleans are allowed in an if condition, Symfony\\\\Component\\\\Console\\\\Helper\\\\ProgressBar\\|null given\\.$#" - count: 1 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Only booleans are allowed in an if condition, array\\ given\\.$#" - count: 4 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Only booleans are allowed in an if condition, int\\<0, max\\> given\\.$#" - count: 2 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Only booleans are allowed in an if condition, int\\<0, max\\>\\|false given\\.$#" - count: 1 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Only booleans are allowed in an if condition, string\\|null given\\.$#" - count: 1 - path: ../src/Composer/Installer/InstallationManager.php - - - - message: "#^Parameter \\#2 \\$offset of function array_splice expects int, int\\|string given\\.$#" - count: 1 - path: ../src/Composer/Installer/InstallationManager.php - - message: "#^Variable method call on \\$this\\(Composer\\\\Installer\\\\InstallationManager\\)\\.$#" count: 2 @@ -4303,31 +4193,11 @@ parameters: count: 1 path: ../src/Composer/Util/Perforce.php - - - message: "#^Casting to string something that's already string\\.$#" - count: 1 - path: ../src/Composer/Util/Platform.php - - - - message: "#^Only booleans are allowed in &&, string\\|false given on the right side\\.$#" - count: 1 - path: ../src/Composer/Util/Platform.php - - message: "#^Only booleans are allowed in a negated boolean, string\\|false given\\.$#" count: 1 path: ../src/Composer/Util/Platform.php - - - message: "#^Only booleans are allowed in a ternary operator condition, array\\\\|false given\\.$#" - count: 1 - path: ../src/Composer/Util/Platform.php - - - - message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#" - count: 2 - path: ../src/Composer/Util/Platform.php - - message: "#^Method Composer\\\\Util\\\\ProcessExecutor\\:\\:doExecute\\(\\) should return int but returns int\\|null\\.$#" count: 1 diff --git a/phpstan/config.neon b/phpstan/config.neon index 3c8e1a20c..5581b24de 100644 --- a/phpstan/config.neon +++ b/phpstan/config.neon @@ -18,9 +18,8 @@ parameters: excludePaths: - '../tests/Composer/Test/Fixtures/*' - '../tests/Composer/Test/Autoload/Fixtures/*' - - '../tests/Composer/Test/Autoload/MinimumVersionSupport/vendor/' + - '../tests/Composer/Test/Autoload/MinimumVersionSupport/vendor/*' - '../tests/Composer/Test/Plugin/Fixtures/*' - - '../tests/Composer/Test/PolyfillTestCase.php' reportUnmatchedIgnoredErrors: false treatPhpDocTypesAsCertain: false diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 2d4bfd265..e3dd15646 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -410,7 +410,7 @@ EOF; // 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]; } @@ -1269,10 +1269,8 @@ INITIALIZER; $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 ''; }, diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 4c87a195d..01d863249 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -529,7 +529,6 @@ class Config } return Preg::replaceCallback('#\{\$(.+)\}#', function ($match) use ($flags) { - assert(is_string($match[1])); return $this->get($match[1], $flags); }, $value); } diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 347d53b5d..0af571c39 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -330,7 +330,7 @@ class EventDispatcher } $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 +354,7 @@ class EventDispatcher $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 +384,6 @@ class EventDispatcher if (Platform::isWindows()) { $exec = Preg::replaceCallback('{^\S+}', static function ($path) { - assert(is_string($path[0])); - return str_replace('/', '\\', $path[0]); }, $exec); } diff --git a/src/Composer/IO/BufferIO.php b/src/Composer/IO/BufferIO.php index 0404287a0..6cf962b84 100644 --- a/src/Composer/IO/BufferIO.php +++ b/src/Composer/IO/BufferIO.php @@ -14,6 +14,8 @@ namespace Composer\IO; 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 @@ use Symfony\Component\Console\Helper\HelperSet; */ 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 @@ class BufferIO extends ConsoleIO */ 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 @@ class BufferIO extends ConsoleIO /** * @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/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 27afa7c3a..89169a6cb 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -39,7 +39,7 @@ use Seld\Signal\SignalHandler; */ class InstallationManager { - /** @var array */ + /** @var list */ private $installers = []; /** @var array */ private $cache = []; @@ -180,7 +180,7 @@ class InstallationManager */ 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 @@ class InstallationManager 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; - } - $batches[] = [$index => $operation]; - $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; + 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 @@ class InstallationManager $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 @@ class InstallationManager $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 @@ class InstallationManager } // execute all downloads first - if (count($promises)) { + if (count($promises) > 0) { $this->waitOnPromises($promises); } @@ -299,7 +302,7 @@ class InstallationManager 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 @@ class InstallationManager $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 @@ class InstallationManager $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 @@ class InstallationManager '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 @@ class InstallationManager '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 @@ class InstallationManager } // execute all prepare => installs/updates/removes => cleanup steps - if (count($promises)) { + if (count($promises) > 0) { $this->waitOnPromises($promises); } @@ -421,14 +424,14 @@ class InstallationManager 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 @@ class InstallationManager 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 @@ class InstallationManager private function markForNotification(PackageInterface $package): void { - if ($package->getNotificationUrl()) { + if ($package->getNotificationUrl() !== null) { $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package; } } @@ -663,7 +666,7 @@ class InstallationManager }); } - if (!empty($promises)) { + if (count($promises) > 0) { $this->loop->wait($promises); } } diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index 7f9814d61..df4067e26 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -284,7 +284,7 @@ class JsonFile 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/src/Composer/Json/JsonFormatter.php b/src/Composer/Json/JsonFormatter.php index 417067241..fa1a3c53f 100644 --- a/src/Composer/Json/JsonFormatter.php +++ b/src/Composer/Json/JsonFormatter.php @@ -68,8 +68,6 @@ class JsonFormatter 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): string { - assert(is_string($match[1])); - assert(is_string($match[2])); $l = strlen($match[1]); if ($l % 2) { @@ -77,7 +75,7 @@ class JsonFormatter // 0xD800..0xDFFF denotes UTF-16 surrogate pair which won't be unescaped // see https://github.com/composer/composer/issues/7510 if (0xD800 <= $code && 0xDFFF >= $code) { - return (string) $match[0]; + return $match[0]; } return str_repeat('\\', $l - 1) . mb_convert_encoding( @@ -87,7 +85,7 @@ class JsonFormatter ); } - return (string) $match[0]; + return $match[0]; }, $buffer); } diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index a8b1e8ea7..0bb0ef869 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -608,7 +608,6 @@ class Filesystem // ensure c: is normalized to C: $prefix = Preg::replaceCallback('{(^|://)[a-z]:$}i', static function (array $m) { - assert(is_string($m[0])); return strtoupper($m[0]); }, $prefix); diff --git a/src/Composer/Util/Platform.php b/src/Composer/Util/Platform.php index dd41904a0..c1a38bac1 100644 --- a/src/Composer/Util/Platform.php +++ b/src/Composer/Util/Platform.php @@ -101,9 +101,6 @@ class Platform } return Preg::replaceCallback('#^(\$|(?P%))(?P\w++)(?(percent)%)(?P.*)#', static function ($matches): string { - assert(is_string($matches['var'])); - assert('' !== $matches['var']); - // Treat HOME as an alias for USERPROFILE on Windows for legacy reasons if (Platform::isWindows() && $matches['var'] === 'HOME') { if ((bool) Platform::getEnv('HOME')) { diff --git a/src/Composer/Util/ProcessExecutor.php b/src/Composer/Util/ProcessExecutor.php index d6a983ef9..bf4b49846 100644 --- a/src/Composer/Util/ProcessExecutor.php +++ b/src/Composer/Util/ProcessExecutor.php @@ -455,8 +455,6 @@ class ProcessExecutor $commandString = is_string($command) ? $command : implode(' ', array_map(self::class.'::escape', $command)); $safeCommand = Preg::replaceCallback('{://(?P[^:/\s]+):(?P[^@\s/]+)@}i', static function ($m): string { - assert(is_string($m['user'])); - // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx) we obfuscate that if (Preg::isMatch('{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+)$}', $m['user'])) { return '://***:***@'; diff --git a/src/Composer/Util/Url.php b/src/Composer/Util/Url.php index 5d703a20d..040d17db0 100644 --- a/src/Composer/Util/Url.php +++ b/src/Composer/Util/Url.php @@ -110,7 +110,6 @@ class Url $url = Preg::replace('{([&?]access_token=)[^&]+}', '$1***', $url); $url = Preg::replaceCallback('{^(?P[a-z0-9]+://)?(?P[^:/\s@]+):(?P[^@\s/]+)@}i', static function ($m): string { - assert(is_string($m['user'])); // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx) we obfuscate that if (Preg::isMatch('{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+|github_pat_[a-zA-Z0-9_]+)$}', $m['user'])) { return $m['prefix'].'***:***@'; diff --git a/tests/Composer/Test/TestCase.php b/tests/Composer/Test/TestCase.php index b1c4c23d7..233e1c3d1 100644 --- a/tests/Composer/Test/TestCase.php +++ b/tests/Composer/Test/TestCase.php @@ -355,7 +355,6 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase { if (Platform::isWindows()) { $cmd = Preg::replaceCallback("/('[^']*')/", static function ($m) { - assert(is_string($m[1])); // Double-quotes are used only when needed $char = (strpbrk($m[1], " \t^&|<>()") !== false || $m[1] === "''") ? '"' : '';