diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml
index 7aa72bb6dd..583c97b199 100644
--- a/.github/workflows/continuous_integration.yml
+++ b/.github/workflows/continuous_integration.yml
@@ -22,7 +22,7 @@ jobs:
strategy:
matrix:
install-args: ['', '--prefer-lowest']
- php-version: ['8.1', '8.2', '8.3', '8.4']
+ php-version: ['8.2', '8.3', '8.4', '8.5']
fail-fast: false
steps:
@@ -73,7 +73,7 @@ jobs:
run: "composer phpstan"
- name: "Run coding standard checks with squizlabs/php_codesniffer on minimum supported PHP version"
- if: matrix.php-version == '8.1'
+ if: matrix.php-version == '8.2'
run: composer cs-check
- name: "Archive code coverage results"
diff --git a/composer.json b/composer.json
index 00ccdb862c..5adda6bc52 100644
--- a/composer.json
+++ b/composer.json
@@ -10,7 +10,7 @@
}
],
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"ext-json": "*",
"composer/package-versions-deprecated": "^1.8",
"phpdocumentor/reflection-docblock": "^5.4",
@@ -28,14 +28,14 @@
},
"require-dev": {
"beberlei/porpaginas": "^2.0",
- "doctrine/coding-standard": "^12.0 || ^13.0",
+ "doctrine/coding-standard": "^13.0",
"ecodev/graphql-upload": "^7.0",
"laminas/laminas-diactoros": "^3.5",
"myclabs/php-enum": "^1.6.6",
"php-coveralls/php-coveralls": "^2.7",
"phpstan/extension-installer": "^1.4",
"phpstan/phpstan": "^2.0",
- "phpunit/phpunit": "^10.5 || ^11.0 || ^12.0",
+ "phpunit/phpunit": "^11.0",
"symfony/var-dumper": "^6.4"
},
"suggest": {
@@ -68,6 +68,11 @@
"composer/package-versions-deprecated": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"phpstan/extension-installer": true
+ },
+ "audit": {
+ "ignore": {
+ "PKSA-5jz8-6tcw-pbk4": "PHPUnit argument-injection via newline in INI values forwarded to child PHP processes (GHSA-qrr6-mg7r-m243). phpunit is a require-dev dependency; the attack surface is INI values in phpunit config or CLI args, which are authored by maintainers/CI and carry the same trust as any other committed code. No fix available for PHPUnit 10.x or 11.x yet — revisit when backport ships or when we bump min PHP to 8.3 and can move to ^12.5.22."
+ }
}
}
}
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 2a564ed45b..691b89f249 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -29,6 +29,9 @@
+
+
diff --git a/src/FieldsBuilder.php b/src/FieldsBuilder.php
index ea8688a18e..8ed8c87a57 100644
--- a/src/FieldsBuilder.php
+++ b/src/FieldsBuilder.php
@@ -878,7 +878,13 @@ private function mapParameters(
$docBlockTypes = [];
foreach ($paramTags as $paramTag) {
- $docBlockTypes[$paramTag->getVariableName()] = $paramTag->getType();
+ $variableName = $paramTag->getVariableName();
+ // Skip malformed @param tags with no variable name (phpdocumentor returns null for
+ // those). PHPStan 8.5 rejects the implicit null-to-empty-string coercion.
+ if ($variableName === null) {
+ continue;
+ }
+ $docBlockTypes[$variableName] = $paramTag->getType();
}
$parameterAnnotationsPerParameter = $this->annotationReader->getParameterAnnotationsPerParameter($refParameters);
diff --git a/src/Mappers/GlobTypeMapperCache.php b/src/Mappers/GlobTypeMapperCache.php
index 032f0f51c9..2339fea83b 100644
--- a/src/Mappers/GlobTypeMapperCache.php
+++ b/src/Mappers/GlobTypeMapperCache.php
@@ -7,6 +7,7 @@
use ReflectionClass;
use function array_keys;
+use function assert;
/**
* The cached results of a GlobTypeMapper
@@ -48,7 +49,11 @@ public function registerAnnotations(ReflectionClass|string $sourceClass, GlobAnn
$this->mapClassToTypeArray[$objectClassName] = $className;
}
+ // GlobAnnotationsCache::withType() sets typeClassName and typeName together, so
+ // inside this branch typeName is guaranteed non-null. Assert the invariant for PHPStan
+ // 8.5+, which is stricter about nullable array offsets.
$typeName = $globAnnotationsCache->getTypeName();
+ assert($typeName !== null);
$this->mapNameToType[$typeName] = $className;
}
diff --git a/src/Mappers/Root/IteratorTypeMapper.php b/src/Mappers/Root/IteratorTypeMapper.php
index 767f0489f6..3d51c54a98 100644
--- a/src/Mappers/Root/IteratorTypeMapper.php
+++ b/src/Mappers/Root/IteratorTypeMapper.php
@@ -206,8 +206,6 @@ private function toGraphQLType(Compound $type, Closure $topToGraphQLType, bool $
*/
private function splitIteratorFromOtherTypes(array &$types): Type|null
{
- $iteratorType = null;
- $key = null;
foreach ($types as $key => $singleDocBlockType) {
if (! ($singleDocBlockType instanceof Object_)) {
continue;
@@ -216,21 +214,17 @@ private function splitIteratorFromOtherTypes(array &$types): Type|null
/** @var class-string