Skip to content

Commit 30add35

Browse files
Merge pull request #4851 from vincentchalamon/chore/symfony-versions
Fix Symfony components compatibility to ^6.1 + migrate code to PHP 8.1 + clean code
2 parents 26cce17 + f4add50 commit 30add35

File tree

796 files changed

+3927
-6826
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

796 files changed

+3927
-6826
lines changed

composer.json

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,30 @@
1212
"homepage": "https://dunglas.fr"
1313
}
1414
],
15+
"repositories": [
16+
{
17+
"type": "git",
18+
"url": "[email protected]:cdaguerre/contexts.git"
19+
}
20+
],
1521
"require": {
1622
"php": ">=8.1",
1723
"doctrine/inflector": "^1.0 || ^2.0",
1824
"fig/link-util": "^1.0",
1925
"psr/cache": "^1.0 || ^2.0 || ^3.0",
2026
"psr/container": "^1.0 || ^2.0",
21-
"symfony/http-foundation": "^4.4 || ^5.1 || ^6.0",
22-
"symfony/http-kernel": "^4.4 || ^5.1 || ^6.0",
23-
"symfony/property-access": "^3.4.19 || ^4.4 || ^5.1 || ^6.0",
24-
"symfony/property-info": "^3.4 || ^4.4 || ^5.2.1 || ^6.0",
25-
"symfony/serializer": "^4.4 || ^5.1 || ^6.0",
26-
"symfony/web-link": "^4.4 || ^5.1 || ^6.0",
27+
"symfony/http-foundation": "^6.1",
28+
"symfony/http-kernel": "^6.1",
29+
"symfony/property-access": "^6.1",
30+
"symfony/property-info": "^6.1",
31+
"symfony/serializer": "^6.1",
32+
"symfony/web-link": "^6.1",
2733
"willdurand/negotiation": "^2.0.3 || ^3.0"
2834
},
2935
"require-dev": {
3036
"behat/behat": "^3.1",
3137
"behat/mink": "^1.9@dev",
38+
"behatch/contexts": "dev-patch-1",
3239
"doctrine/cache": "^1.11 || ^2.1",
3340
"doctrine/common": "^2.11 || ^3.0",
3441
"doctrine/data-fixtures": "^1.2.2",
@@ -54,37 +61,37 @@
5461
"psr/log": "^1.0 || ^2.0 || ^3.0",
5562
"ramsey/uuid": "^3.7 || ^4.0",
5663
"ramsey/uuid-doctrine": "^1.4",
57-
"soyuka/contexts": "dev-main",
64+
"rector/rector": "^0.13.9",
5865
"soyuka/stubs-mongodb": "^1.0",
59-
"symfony/asset": "^3.4 || ^4.4 || ^5.1 || ^6.0",
60-
"symfony/browser-kit": "^4.4 || ^5.1 || ^6.0",
61-
"symfony/cache": "^3.4 || ^4.4 || ^5.1 || ^6.0",
62-
"symfony/config": "^3.4 || ^4.4 || ^5.1 || ^6.0",
63-
"symfony/console": "^3.4 || ^4.4 || ^5.1 || ^6.0",
64-
"symfony/css-selector": "^3.4 || ^4.4 || ^5.1 || ^6.0",
65-
"symfony/debug": "^3.4 || ^4.4 || ^5.1 || ^6.0",
66-
"symfony/dependency-injection": "^3.4 || ^4.4 || ^5.1 || ^6.0",
67-
"symfony/doctrine-bridge": "^3.4 || ^4.4 || ^5.1 || ^6.0",
68-
"symfony/dom-crawler": "^3.4 || ^4.4 || ^5.1 || ^6.0",
69-
"symfony/event-dispatcher": "^3.4 || ^4.4 || ^5.1 || ^6.0",
70-
"symfony/expression-language": "^3.4 || ^4.4 || ^5.1 || ^6.0",
71-
"symfony/finder": "^3.4 || ^4.4 || ^5.1 || ^6.0",
72-
"symfony/form": "^3.4 || ^4.4 || ^5.1 || ^6.0",
73-
"symfony/framework-bundle": "^4.4 || ^5.1 || ^6.0",
74-
"symfony/http-client": "^4.4 || ^5.1 || ^6.0",
75-
"symfony/intl": "^4.4 || ^5.3 || ^6.0",
66+
"symfony/asset": "^6.1",
67+
"symfony/browser-kit": "^6.1",
68+
"symfony/cache": "^6.1",
69+
"symfony/config": "^6.1",
70+
"symfony/console": "^6.1",
71+
"symfony/css-selector": "^6.1",
72+
"symfony/dependency-injection": "^6.1",
73+
"symfony/doctrine-bridge": "^6.1",
74+
"symfony/dom-crawler": "^6.1",
75+
"symfony/error-handler": "^6.1",
76+
"symfony/event-dispatcher": "^6.1",
77+
"symfony/expression-language": "^6.1",
78+
"symfony/finder": "^6.1",
79+
"symfony/form": "^6.1",
80+
"symfony/framework-bundle": "^6.1",
81+
"symfony/http-client": "^6.1",
82+
"symfony/intl": "^6.1",
7683
"symfony/maker-bundle": "^1.24",
7784
"symfony/mercure-bundle": "*",
78-
"symfony/messenger": "^4.4 || ^5.1 || ^6.0",
79-
"symfony/phpunit-bridge": "^5.4 || ^6.0",
80-
"symfony/routing": "^3.4 || ^4.4 || ^5.1 || ^6.0",
81-
"symfony/security-bundle": "^3.4 || ^4.4 || ^5.1 || ^6.0",
82-
"symfony/security-core": "^4.4 || ^5.1 || ^6.0",
83-
"symfony/twig-bundle": "^3.4 || ^4.4 || ^5.1 || ^6.0",
84-
"symfony/uid": "^5.1 || ^6.0",
85-
"symfony/validator": "^3.4 || ^4.4 || ^5.1 || ^6.0",
86-
"symfony/web-profiler-bundle": "^4.4 || ^5.1 || ^6.0",
87-
"symfony/yaml": "^3.4 || ^4.4 || ^5.1 || ^6.0",
85+
"symfony/messenger": "^6.1",
86+
"symfony/phpunit-bridge": "^6.1",
87+
"symfony/routing": "^6.1",
88+
"symfony/security-bundle": "^6.1",
89+
"symfony/security-core": "^6.1",
90+
"symfony/twig-bundle": "^6.1",
91+
"symfony/uid": "^6.1",
92+
"symfony/validator": "^6.1",
93+
"symfony/web-profiler-bundle": "^6.1",
94+
"symfony/yaml": "^6.1",
8895
"twig/twig": "^1.42.3 || ^2.12 || ^3.0",
8996
"webonyx/graphql-php": "^14.0"
9097
},
@@ -138,7 +145,7 @@
138145
"dev-main": "3.0.x-dev"
139146
},
140147
"symfony": {
141-
"require": "^3.4 || ^4.4 || ^5.1 || ^6.0"
148+
"require": "^6.1"
142149
}
143150
}
144151
}

features/main/operation_resource.feature

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ Feature: Resource operations
2626
"""
2727
{"name": "Patched"}
2828
"""
29-
Then print last JSON response
3029
Then the response status code should be 200
3130
And the response should be in JSON
3231
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"

phpstan.neon.dist

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ parameters:
3939
- handleNotFound
4040
ignoreErrors:
4141
# False positives
42+
-
43+
message: '#but database expects#'
44+
paths:
45+
- tests/Fixtures/TestBundle/Entity/
46+
- '#Cannot call method add\(\) on iterable.#'
4247
-
4348
message: '#is never read, only written.#'
4449
paths:
@@ -49,14 +54,20 @@ parameters:
4954
message: '#is never written, only read.#'
5055
paths:
5156
- tests/Fixtures/TestBundle/Document/
52-
- tests/Fixtures/TestBundle/Entity/
57+
-
58+
message: '#Parameter \#1 \$constraint of method#'
59+
paths:
60+
- tests/Symfony/Validator/Metadata/Property/Restriction/
61+
-
62+
message: '#expects ApiPlatform\\Metadata\\GraphQl\\Operation\|null, ApiPlatform\\Metadata\\Operation given#'
63+
paths:
64+
- tests/GraphQl/Resolver/Factory/
5365
- '#Access to an undefined property Prophecy\\Prophecy\\ObjectProphecy<(\\?[a-zA-Z0-9_]+)+>::\$[a-zA-Z0-9_]+#'
5466
# https://github.com/willdurand/Negotiation/issues/89#issuecomment-513283286
5567
-
5668
message: '#Call to an undefined method Negotiation\\AcceptHeader::getType\(\)\.#'
5769
path: src/Symfony/EventListener/AddFormatListener.php
5870
- '#Parameter \#1 \$vars of class GraphQL\\Language\\AST\\(IntValue|ObjectField|ObjectValue|BooleanValue|ListValue|StringValue)Node constructor expects array<bool\|float\|GraphQL\\Language\\AST\\Location\|GraphQL\\Language\\AST\\NameNode\|GraphQL\\Language\\AST\\NodeList\|GraphQL\\Language\\AST\\SelectionSetNode\|int\|string\|null>, array<string, .+> given\.#'
59-
- '#Parameter \#1 \$defaultContext of class Symfony\\Component\\Serializer\\Encoder\\Json(De|En)code constructor expects array, (int|true) given\.#'
6071
-
6172
message: '#Parameter \#1 \$objectValue of method GraphQL\\Type\\Definition\\InterfaceType::resolveType\(\) expects object, array(<string, string>)? given.#'
6273
path: tests/GraphQl/Type/TypeBuilderTest.php
@@ -74,23 +85,10 @@ parameters:
7485
-
7586
message: "#Call to function method_exists\\(\\) with ApiPlatform\\\\JsonApi\\\\Serializer\\\\ItemNormalizer and 'setCircularReferenc…' will always evaluate to false\\.#"
7687
path: tests/JsonApi/Serializer/ItemNormalizerTest.php
77-
-
78-
message: "#Dead catch - JsonException is never thrown in the try block.#"
79-
path: src/Symfony/Bundle/Test/Response.php
8088
# See https://github.com/phpstan/phpstan-symfony/issues/27
8189
-
8290
message: '#^Service "[^"]+" is private.$#'
8391
path: src
8492
-
8593
message: '#^Property .+ is unused.$#'
8694
path: tests/Doctrine/Odm/PropertyInfo/Fixtures/DoctrineDummy.php
87-
-
88-
message: '#Call to an undefined method Symfony\\Component\\PropertyInfo\\Type::getCollectionValueType\(\)#'
89-
path: src
90-
-
91-
message: '#Call to an undefined method Symfony\\Component\\PropertyInfo\\Type::getCollectionKeyType\(\)#'
92-
path: src
93-
# Skipped tests, we do this on purpose
94-
-
95-
message: "#Access to an undefined static property static\\([^)]+\\)::\\$container.$#"
96-
path: tests

rector.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
15+
use Rector\Config\RectorConfig;
16+
use Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector;
17+
use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
18+
use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
19+
use Rector\PHPUnit\Rector\Class_\AddSeeTestAnnotationRector;
20+
use Rector\PHPUnit\Rector\MethodCall\AssertEqualsToSameRector;
21+
use Rector\PHPUnit\Set\PHPUnitSetList;
22+
use Rector\Renaming\Rector\MethodCall\RenameMethodRector;
23+
use Rector\Set\ValueObject\LevelSetList;
24+
use Rector\Set\ValueObject\SetList;
25+
use Rector\TypeDeclaration\Rector\ClassMethod\ArrayShapeFromConstantArrayReturnRector;
26+
27+
return static function (RectorConfig $rectorConfig): void {
28+
$rectorConfig->paths([
29+
__DIR__.'/src',
30+
__DIR__.'/tests',
31+
]);
32+
$rectorConfig->skip([
33+
__DIR__.'/tests/Fixtures/app/var',
34+
AddSeeTestAnnotationRector::class,
35+
ArrayShapeFromConstantArrayReturnRector::class,
36+
NullToStrictStringFuncCallArgRector::class,
37+
ReadOnlyPropertyRector::class => [
38+
__DIR__.'/tests/Fixtures/TestBundle/Document',
39+
__DIR__.'/tests/Fixtures/TestBundle/Entity',
40+
],
41+
RemoveParentCallWithoutParentRector::class => [
42+
__DIR__.'/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php',
43+
],
44+
RenameMethodRector::class => [
45+
__DIR__.'/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php',
46+
],
47+
AssertEqualsToSameRector::class,
48+
]);
49+
$rectorConfig->phpstanConfig(__DIR__.'/phpstan.neon.dist');
50+
$rectorConfig->importNames();
51+
$rectorConfig->importShortClasses(false);
52+
53+
$rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
54+
55+
$rectorConfig->sets([
56+
LevelSetList::UP_TO_PHP_81,
57+
SetList::TYPE_DECLARATION_STRICT,
58+
]);
59+
60+
// PHPUnit
61+
$rectorConfig->sets([
62+
PHPUnitSetList::PHPUNIT_91,
63+
PHPUnitSetList::PHPUNIT_CODE_QUALITY,
64+
PHPUnitSetList::PHPUNIT_EXCEPTION,
65+
PHPUnitSetList::REMOVE_MOCKS,
66+
PHPUnitSetList::PHPUNIT_SPECIFIC_METHOD,
67+
PHPUnitSetList::PHPUNIT_YIELD_DATA_PROVIDER,
68+
]);
69+
};

src/Action/EntrypointAction.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,8 @@
2323
*/
2424
final class EntrypointAction
2525
{
26-
private $resourceNameCollectionFactory;
27-
28-
public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory)
26+
public function __construct(private readonly ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory)
2927
{
30-
$this->resourceNameCollectionFactory = $resourceNameCollectionFactory;
3128
}
3229

3330
public function __invoke(): Entrypoint

src/Action/ExceptionAction.php

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,13 @@
1919
use ApiPlatform\Util\ErrorFormatGuesser;
2020
use ApiPlatform\Util\OperationRequestInitiatorTrait;
2121
use ApiPlatform\Util\RequestAttributesExtractor;
22-
use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException;
2322
use Symfony\Component\ErrorHandler\Exception\FlattenException;
2423
use Symfony\Component\HttpFoundation\Request;
2524
use Symfony\Component\HttpFoundation\Response;
2625
use Symfony\Component\Serializer\SerializerInterface;
2726

2827
/**
29-
* Renders a normalized exception for a given {@see FlattenException} or {@see LegacyFlattenException}.
28+
* Renders a normalized exception for a given {@see FlattenException}.
3029
*
3130
* @author Baptiste Meyer <[email protected]>
3231
* @author Kévin Dunglas <[email protected]>
@@ -35,28 +34,19 @@ final class ExceptionAction
3534
{
3635
use OperationRequestInitiatorTrait;
3736

38-
private $serializer;
39-
private $errorFormats;
40-
private $exceptionToStatus;
41-
4237
/**
4338
* @param array $errorFormats A list of enabled error formats
4439
* @param array $exceptionToStatus A list of exceptions mapped to their HTTP status code
4540
*/
46-
public function __construct(SerializerInterface $serializer, array $errorFormats, array $exceptionToStatus = [], ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null)
41+
public function __construct(private readonly SerializerInterface $serializer, private readonly array $errorFormats, private readonly array $exceptionToStatus = [], ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null)
4742
{
48-
$this->serializer = $serializer;
49-
$this->errorFormats = $errorFormats;
50-
$this->exceptionToStatus = $exceptionToStatus;
5143
$this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory;
5244
}
5345

5446
/**
5547
* Converts an exception to a JSON response.
56-
*
57-
* @param FlattenException|LegacyFlattenException $exception
5848
*/
59-
public function __invoke($exception, Request $request): Response
49+
public function __invoke(FlattenException $exception, Request $request): Response
6050
{
6151
$operation = $this->initializeOperation($request);
6252
$exceptionClass = $exception->getClass();

src/Api/Entrypoint.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,8 @@
2222
*/
2323
final class Entrypoint
2424
{
25-
private $resourceNameCollection;
26-
27-
public function __construct(ResourceNameCollection $resourceNameCollection)
25+
public function __construct(private readonly ResourceNameCollection $resourceNameCollection)
2826
{
29-
$this->resourceNameCollection = $resourceNameCollection;
3027
}
3128

3229
public function getResourceNameCollection(): ResourceNameCollection

src/Api/FilterLocatorTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
*/
2626
trait FilterLocatorTrait
2727
{
28-
private ?ContainerInterface $filterLocator;
28+
private ?ContainerInterface $filterLocator = null;
2929

3030
/**
3131
* Sets a filter locator with a backward compatibility.

src/Api/FormatMatcher.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ final class FormatMatcher
2323
/**
2424
* @var array<string, string[]>
2525
*/
26-
private $formats;
26+
private readonly array $formats;
2727

2828
/**
2929
* @param array<string, string[]|string> $formats

src/Api/IdentifiersExtractor.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,12 @@
3333
final class IdentifiersExtractor implements IdentifiersExtractorInterface
3434
{
3535
use ResourceClassInfoTrait;
36+
private readonly PropertyAccessorInterface $propertyAccessor;
3637

37-
private $propertyNameCollectionFactory;
38-
private $propertyMetadataFactory;
39-
private $propertyAccessor;
40-
41-
public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, PropertyAccessorInterface $propertyAccessor = null)
38+
public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, private readonly PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, private readonly PropertyMetadataFactoryInterface $propertyMetadataFactory, PropertyAccessorInterface $propertyAccessor = null)
4239
{
4340
$this->resourceMetadataFactory = $resourceMetadataFactory;
4441
$this->resourceClassResolver = $resourceClassResolver;
45-
$this->propertyNameCollectionFactory = $propertyNameCollectionFactory;
46-
$this->propertyMetadataFactory = $propertyMetadataFactory;
4742
$this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
4843
}
4944

@@ -61,7 +56,7 @@ public function getIdentifiersFromItem($item, Operation $operation = null, array
6156
}
6257

6358
$resourceClass = $this->getResourceClass($item, true);
64-
$operation = $operation ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation(null, false, true);
59+
$operation ??= $this->resourceMetadataFactory->create($resourceClass)->getOperation(null, false, true);
6560

6661
if ($operation instanceof HttpOperation) {
6762
$links = $operation->getUriVariables();
@@ -70,7 +65,7 @@ public function getIdentifiersFromItem($item, Operation $operation = null, array
7065
}
7166

7267
foreach ($links ?? [] as $link) {
73-
if (1 < \count($link->getIdentifiers())) {
68+
if (1 < (is_countable($link->getIdentifiers()) ? \count($link->getIdentifiers()) : 0)) {
7469
$compositeIdentifiers = [];
7570
foreach ($link->getIdentifiers() as $identifier) {
7671
$compositeIdentifiers[$identifier] = $this->getIdentifierValue($item, $link->getFromClass() ?? $resourceClass, $identifier, $link->getParameterName());

0 commit comments

Comments
 (0)