Skip to content

Commit b47ccea

Browse files
authored
Test and fix API Platform with Symfony 4.4 (#3009)
* Test and fix API Platform with Symfony 4.4 * Fix more deprecations * Add CI jobs for testing next release of Symfony * Fix TwigBundle config * Require HttpFoundation 4.3.6 * Use renamed HttpKernel event classes To ensure forward compatibility with Symfony 5.0 * Fix TypeError due to invalid call to DenormalizerInterface::supportsDenormalization * Fix tests by preventing to install Mink dev * Fix tests by making the firewall stateless * Fix tests * Temporarily exclude Doctrine master * Fix CSV issue * Fix CS
1 parent f50b5ee commit b47ccea

File tree

63 files changed

+469
-335
lines changed

Some content is hidden

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

63 files changed

+469
-335
lines changed

.github/workflows/ci.yml

Lines changed: 156 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ env:
1111
EXT_MONGODB_VERSION: '1.5.5'
1212
EXT_PCOV_VERSION: '1.0.6'
1313
LEGACY: '0'
14-
SYMFONY_REQUIRE: ^3.4 || ^4.0
14+
SYMFONY_REQUIRE: ^3.4 || ^4.0 || ^5.0
1515

1616
jobs:
1717
phpunit:
@@ -173,7 +173,7 @@ jobs:
173173
run: |
174174
mkdir -p /tmp/api-platform/core/var
175175
ln -s /tmp/api-platform/core/var tests/Fixtures/app/var
176-
tests/Fixtures/app/console cache:clear --
176+
tests/Fixtures/app/console cache:clear --ansi
177177
- name: Enable code coverage
178178
if: matrix.coverage
179179
run: echo '::set-env name=COVERAGE::1'
@@ -1018,7 +1018,7 @@ jobs:
10181018
run: |
10191019
mkdir -p /tmp/api-platform/core/var
10201020
ln -s /tmp/api-platform/core/var tests/Fixtures/app/var
1021-
tests/Fixtures/app/console cache:clear --
1021+
tests/Fixtures/app/console cache:clear --ansi
10221022
- name: Enable code coverage
10231023
if: matrix.coverage
10241024
run: echo '::set-env name=COVERAGE::1'
@@ -1107,10 +1107,162 @@ jobs:
11071107
run: |
11081108
mkdir -p build/logs/phpunit
11091109
vendor/bin/phpunit --log-junit build/logs/phpunit/junit.xml --colors=always
1110-
continue-on-error: true
11111110
- name: Upload test artifacts
11121111
if: always()
11131112
uses: actions/upload-artifact@v1
11141113
with:
11151114
name: phpunit-logs-php${{ matrix.php }}-no-deprecations
11161115
path: build/logs/phpunit
1116+
1117+
phpunit-symfony-next:
1118+
name: PHPUnit (PHP ${{ matrix.php }}) (Symfony ${{ matrix.symfony }})
1119+
runs-on: ubuntu-latest
1120+
container:
1121+
image: php:${{ matrix.php }}-alpine
1122+
options: >-
1123+
--tmpfs /tmp:exec
1124+
strategy:
1125+
matrix:
1126+
php:
1127+
- '7.3'
1128+
symfony:
1129+
- '4.4'
1130+
fail-fast: false
1131+
timeout-minutes: 20
1132+
steps:
1133+
- name: Checkout
1134+
uses: actions/checkout@v1
1135+
- name: Install system packages
1136+
run: |
1137+
apk add \
1138+
jq \
1139+
moreutils \
1140+
unzip \
1141+
- name: Install mongodb PHP extension
1142+
run: |
1143+
apk add $PHPIZE_DEPS
1144+
pecl install mongodb-$EXT_MONGODB_VERSION
1145+
docker-php-ext-enable mongodb
1146+
- name: Disable PHP memory limit
1147+
run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini
1148+
- name: Install Composer
1149+
run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet
1150+
- name: Install Symfony Flex
1151+
run: |
1152+
composer global require --prefer-dist --no-progress --no-suggest --ansi \
1153+
symfony/flex
1154+
- name: Allow unstable project dependencies
1155+
run: |
1156+
jq '. + {"minimum-stability": "dev"}' composer.json | sponge composer.json
1157+
- name: Update project dependencies
1158+
run: |
1159+
mkdir -p /tmp/api-platform/core/vendor
1160+
ln -s /tmp/api-platform/core/vendor vendor
1161+
composer update --no-progress --no-suggest --ansi
1162+
- name: Flag held back Symfony packages
1163+
env:
1164+
symfony_version: ${{ matrix.symfony }}
1165+
run: |
1166+
version_pattern=$symfony_version.x-dev
1167+
if [ "${symfony_version%.4}" != "$symfony_version" ]; then
1168+
current_major=${symfony_version%.4}
1169+
next_major=$((current_major + 1))
1170+
version_pattern=$version_pattern'|'$next_major.0.x-dev'|'dev-master
1171+
fi
1172+
version_pattern=$(echo "$version_pattern" | sed -r 's/\./\\./g')
1173+
symfony_packages=$(composer show symfony/* | tr -s ' ' '\t' | cut -f1-2 | grep -vE 'polyfill|contracts|mercure')
1174+
! echo "$symfony_packages" | grep -vE "$version_pattern"
1175+
continue-on-error: true
1176+
- name: Clear test app cache
1177+
run: |
1178+
mkdir -p /tmp/api-platform/core/var
1179+
ln -s /tmp/api-platform/core/var tests/Fixtures/app/var
1180+
tests/Fixtures/app/console cache:clear --ansi
1181+
- name: Run PHPUnit tests
1182+
run: |
1183+
mkdir -p build/logs/phpunit
1184+
vendor/bin/phpunit --log-junit build/logs/phpunit/junit.xml --colors=always
1185+
- name: Upload test artifacts
1186+
if: always()
1187+
uses: actions/upload-artifact@v1
1188+
with:
1189+
name: phpunit-logs-php${{ matrix.php }}-symfony${{ matrix.symfony }}
1190+
path: build/logs/phpunit
1191+
1192+
behat-symfony-next:
1193+
name: Behat (PHP ${{ matrix.php }}) (Symfony ${{ matrix.symfony }})
1194+
runs-on: ubuntu-latest
1195+
container:
1196+
image: php:${{ matrix.php }}-alpine
1197+
options: >-
1198+
--tmpfs /tmp:exec
1199+
strategy:
1200+
matrix:
1201+
php:
1202+
- '7.3'
1203+
symfony:
1204+
- '4.4'
1205+
fail-fast: false
1206+
timeout-minutes: 20
1207+
steps:
1208+
- name: Checkout
1209+
uses: actions/checkout@v1
1210+
- name: Install system packages
1211+
run: |
1212+
apk add \
1213+
jq \
1214+
moreutils \
1215+
unzip \
1216+
- name: Install mongodb PHP extension
1217+
run: |
1218+
apk add $PHPIZE_DEPS
1219+
pecl install mongodb-$EXT_MONGODB_VERSION
1220+
docker-php-ext-enable mongodb
1221+
- name: Disable PHP memory limit
1222+
run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini
1223+
- name: Install Composer
1224+
run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet
1225+
- name: Install Symfony Flex
1226+
run: |
1227+
composer global require --prefer-dist --no-progress --no-suggest --ansi \
1228+
symfony/flex
1229+
- name: Allow unstable project dependencies
1230+
run: |
1231+
jq '. + {"minimum-stability": "dev"}' composer.json | sponge composer.json
1232+
- name: Update project dependencies
1233+
run: |
1234+
mkdir -p /tmp/api-platform/core/vendor
1235+
ln -s /tmp/api-platform/core/vendor vendor
1236+
composer update --no-progress --no-suggest --ansi
1237+
- name: Flag held back Symfony packages
1238+
env:
1239+
symfony_version: ${{ matrix.symfony }}
1240+
run: |
1241+
version_pattern=$symfony_version.x-dev
1242+
if [ "${symfony_version%.4}" != "$symfony_version" ]; then
1243+
current_major=${symfony_version%.4}
1244+
next_major=$((current_major + 1))
1245+
version_pattern=$version_pattern'|'$next_major.0.x-dev'|'dev-master
1246+
fi
1247+
version_pattern=$(echo "$version_pattern" | sed -r 's/\./\\./g')
1248+
symfony_packages=$(composer show symfony/* | tr -s ' ' '\t' | cut -f1-2 | grep -vE 'polyfill|contracts|mercure')
1249+
! echo "$symfony_packages" | grep -vE "$version_pattern"
1250+
continue-on-error: true
1251+
- name: Enable legacy integrations
1252+
if: startsWith(matrix.php, '7.3')
1253+
run: echo '::set-env name=LEGACY::1'
1254+
- name: Clear test app cache
1255+
run: |
1256+
mkdir -p /tmp/api-platform/core/var
1257+
ln -s /tmp/api-platform/core/var tests/Fixtures/app/var
1258+
tests/Fixtures/app/console cache:clear --ansi
1259+
- name: Run Behat tests
1260+
run: |
1261+
mkdir -p build/logs/behat
1262+
vendor/bin/behat --format=progress --out=std --format=junit --out=build/logs/behat/junit --profile="$(if [ "$LEGACY" = '1' ]; then echo 'default-legacy'; else echo 'default'; fi)" --no-interaction --colors
1263+
- name: Upload test artifacts
1264+
if: always()
1265+
uses: actions/upload-artifact@v1
1266+
with:
1267+
name: behat-logs-php${{ matrix.php }}-symfony${{ matrix.symfony }}
1268+
path: build/logs/behat

composer.json

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@
1515
"require": {
1616
"php": ">=7.1",
1717
"doctrine/inflector": "^1.0",
18+
"fig/link-util": "^1.0",
1819
"psr/cache": "^1.0",
1920
"psr/container": "^1.0",
20-
"symfony/http-foundation": "^3.4 || ^4.0",
21-
"symfony/http-kernel": "^3.4 || ^4.0",
22-
"symfony/property-access": "^3.4 || ^4.0",
23-
"symfony/property-info": "^3.4 || ^4.0",
24-
"symfony/serializer": "^4.3",
25-
"symfony/web-link": "^4.1",
21+
"symfony/http-foundation": "^4.3.6 || ^5.0",
22+
"symfony/http-kernel": "^4.3 || ^5.0",
23+
"symfony/property-access": "^3.4 || ^4.0 || ^5.0",
24+
"symfony/property-info": "^3.4 || ^4.0 || ^5.0",
25+
"symfony/serializer": "^4.3 || ^5.0",
26+
"symfony/web-link": "^4.1 || ^5.0",
2627
"willdurand/negotiation": "^2.0.3"
2728
},
2829
"require-dev": {
@@ -35,7 +36,7 @@
3536
"doctrine/annotations": "^1.7",
3637
"doctrine/common": "^2.11",
3738
"doctrine/data-fixtures": "^1.2.2",
38-
"doctrine/doctrine-bundle": "^1.8",
39+
"doctrine/doctrine-bundle": "^1.8 || ^2.0",
3940
"doctrine/doctrine-cache-bundle": "^1.3.5",
4041
"doctrine/mongodb-odm": "^2.0",
4142
"doctrine/mongodb-odm-bundle": "^4.0",
@@ -59,32 +60,32 @@
5960
"ramsey/uuid": "^3.7",
6061
"ramsey/uuid-doctrine": "^1.4",
6162
"sebastian/object-enumerator": "^3.0.3",
62-
"symfony/asset": "^3.4 || ^4.0",
63-
"symfony/browser-kit": "^4.3",
64-
"symfony/cache": "^3.4 || ^4.0",
65-
"symfony/config": "^3.4 || ^4.0",
66-
"symfony/console": "^3.4 || ^4.0",
67-
"symfony/css-selector": "^3.4 || ^4.0",
68-
"symfony/debug": "^3.4 || ^4.0",
69-
"symfony/dependency-injection": "^3.4 || ^4.0",
70-
"symfony/doctrine-bridge": "^3.4 || ^4.0",
71-
"symfony/dom-crawler": "^3.4 || ^4.0",
72-
"symfony/event-dispatcher": "^3.4 || ^4.0",
73-
"symfony/expression-language": "^3.4 || ^4.0",
74-
"symfony/finder": "^3.4 || ^4.0",
75-
"symfony/form": "^3.4 || ^4.0",
76-
"symfony/framework-bundle": "^4.3.2",
77-
"symfony/http-client": "^4.3",
63+
"symfony/asset": "^3.4 || ^4.0 || ^5.0",
64+
"symfony/browser-kit": "^4.3 || ^5.0",
65+
"symfony/cache": "^3.4 || ^4.0 || ^5.0",
66+
"symfony/config": "^3.4 || ^4.0 || ^5.0",
67+
"symfony/console": "^3.4 || ^4.0 || ^5.0",
68+
"symfony/css-selector": "^3.4 || ^4.0 || ^5.0",
69+
"symfony/debug": "^3.4 || ^4.0 || ^5.0",
70+
"symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0",
71+
"symfony/doctrine-bridge": "^3.4 || ^4.0 || ^5.0",
72+
"symfony/dom-crawler": "^3.4 || ^4.0 || ^5.0",
73+
"symfony/event-dispatcher": "^3.4 || ^4.0 || ^5.0",
74+
"symfony/expression-language": "^3.4 || ^4.0 || ^5.0",
75+
"symfony/finder": "^3.4 || ^4.0 || ^5.0",
76+
"symfony/form": "^3.4 || ^4.0 || ^5.0",
77+
"symfony/framework-bundle": "^4.3.2 || ^5.0",
78+
"symfony/http-client": "^4.3 || ^5.0",
7879
"symfony/mercure-bundle": "*",
79-
"symfony/messenger": "^4.3",
80-
"symfony/phpunit-bridge": "^4.3@dev",
81-
"symfony/routing": "^3.4 || ^4.3",
82-
"symfony/security-bundle": "^3.4 || ^4.0",
83-
"symfony/security-core": "^4.3",
84-
"symfony/twig-bundle": "^3.4 || ^4.0",
85-
"symfony/validator": "^3.4 || ^4.0",
86-
"symfony/web-profiler-bundle": "^4.2",
87-
"symfony/yaml": "^3.4 || ^4.0",
80+
"symfony/messenger": "^4.3 || ^5.0",
81+
"symfony/phpunit-bridge": "^4.3 || ^5.0",
82+
"symfony/routing": "^3.4 || ^4.3 || ^5.0",
83+
"symfony/security-bundle": "^3.4 || ^4.0 || ^5.0",
84+
"symfony/security-core": "^4.3 || ^5.0",
85+
"symfony/twig-bundle": "^3.4 || ^4.0 || ^5.0",
86+
"symfony/validator": "^3.4 || ^4.0 || ^5.0",
87+
"symfony/web-profiler-bundle": "^4.2 || ^5.0",
88+
"symfony/yaml": "^3.4 || ^4.0 || ^5.0",
8889
"twig/twig": "^1.42.3 || ^2.12",
8990
"webonyx/graphql-php": ">=0.13.1 <1.0"
9091
},

features/main/content_negotiation.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ Feature: Content Negotiation support
124124
Then the response status code should be 406
125125
And the header "Content-Type" should be equal to "application/problem+json; charset=utf-8"
126126

127-
Scenario: Post an CSV body allowed on a single resource
127+
Scenario: Post CSV body allowed on a single resource
128128
When I add "Accept" header equal to "application/xml"
129129
And I add "Content-Type" header equal to "text/csv"
130130
And I send a "POST" request to "/dummy_custom_formats" with body:

phpstan.neon.dist

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,14 @@ parameters:
106106
- '#Method ApiPlatform\\Core\\Bridge\\Doctrine\\Orm\\Filter\\(Abstract|Exists|Order)Filter::filterProperty\(\) invoked with 7 parameters, 5-6 required\.#'
107107
- '#Method ApiPlatform\\Core\\Bridge\\Doctrine\\Orm\\Filter\\(AbstractFilter|FilterInterface)::apply\(\) invoked with 5 parameters, 3-4 required\.#'
108108
- '#Method ApiPlatform\\Core\\PathResolver\\OperationPathResolverInterface::resolveOperationPath\(\) invoked with 4 parameters, 3 required\.#'
109+
110+
# Expected, due to forward compatibility
111+
-
112+
message: '#Class Symfony\\Component\\ErrorRenderer\\ErrorRenderer not found\.#'
113+
path: %currentWorkingDirectory%/tests/Fixtures/app/AppKernel.php
114+
-
115+
message: '#Parameter \$exception of method ApiPlatform\\Core\\Action\\ExceptionAction::__invoke\(\) has invalid typehint type Symfony\\Component\\ErrorRenderer\\Exception\\FlattenException\.#'
116+
path: %currentWorkingDirectory%/src/Action/ExceptionAction.php
117+
-
118+
message: '#Call to method get(Class|Headers|StatusCode)\(\) on an unknown class Symfony\\Component\\ErrorRenderer\\Exception\\FlattenException\.#'
119+
path: %currentWorkingDirectory%/src/Action/ExceptionAction.php

src/Action/ExceptionAction.php

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,14 @@
1414
namespace ApiPlatform\Core\Action;
1515

1616
use ApiPlatform\Core\Util\ErrorFormatGuesser;
17-
use Symfony\Component\Debug\Exception\FlattenException;
17+
use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException;
18+
use Symfony\Component\ErrorRenderer\Exception\FlattenException;
1819
use Symfony\Component\HttpFoundation\Request;
1920
use Symfony\Component\HttpFoundation\Response;
2021
use Symfony\Component\Serializer\SerializerInterface;
2122

2223
/**
23-
* Renders a normalized exception for a given {@see \Symfony\Component\Debug\Exception\FlattenException}.
24-
*
25-
* Usage:
26-
*
27-
* $exceptionAction = new ExceptionAction(
28-
* new Serializer(),
29-
* [
30-
* 'jsonproblem' => ['application/problem+json'],
31-
* 'jsonld' => ['application/ld+json'],
32-
* ],
33-
* [
34-
* ExceptionInterface::class => Response::HTTP_BAD_REQUEST,
35-
* InvalidArgumentException::class => Response::HTTP_BAD_REQUEST,
36-
* ]
37-
* );
24+
* Renders a normalized exception for a given {@see FlattenException} or {@see LegacyFlattenException}.
3825
*
3926
* @author Baptiste Meyer <[email protected]>
4027
* @author Kévin Dunglas <[email protected]>
@@ -46,7 +33,7 @@ final class ExceptionAction
4633
private $exceptionToStatus;
4734

4835
/**
49-
* @param array $errorFormats A list of enabled formats, the first one will be the default
36+
* @param array $errorFormats A list of enabled error formats
5037
* @param array $exceptionToStatus A list of exceptions mapped to their HTTP status code
5138
*/
5239
public function __construct(SerializerInterface $serializer, array $errorFormats, array $exceptionToStatus = [])
@@ -58,8 +45,10 @@ public function __construct(SerializerInterface $serializer, array $errorFormats
5845

5946
/**
6047
* Converts an exception to a JSON response.
48+
*
49+
* @param FlattenException|LegacyFlattenException $exception
6150
*/
62-
public function __invoke(FlattenException $exception, Request $request): Response
51+
public function __invoke($exception, Request $request): Response
6352
{
6453
$exceptionClass = $exception->getClass();
6554
$statusCode = $exception->getStatusCode();

src/Bridge/Doctrine/EventListener/WriteListener.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use ApiPlatform\Core\EventListener\WriteListener as BaseWriteListener;
1717
use Doctrine\Common\Persistence\ManagerRegistry;
1818
use Doctrine\Common\Persistence\ObjectManager;
19-
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
19+
use Symfony\Component\HttpKernel\Event\ViewEvent;
2020

2121
/**
2222
* Bridges Doctrine and the API system.
@@ -39,10 +39,10 @@ public function __construct(ManagerRegistry $managerRegistry)
3939
/**
4040
* Persists, updates or delete data return by the controller if applicable.
4141
*/
42-
public function onKernelView(GetResponseForControllerResultEvent $event): void
42+
public function onKernelView(ViewEvent $event): void
4343
{
4444
$request = $event->getRequest();
45-
if ($request->isMethodSafe(false)) {
45+
if ($request->isMethodSafe()) {
4646
return;
4747
}
4848

src/Bridge/Doctrine/Orm/ItemDataProvider.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,7 @@ public function getItem(string $resourceClass, $id, string $operationName = null
7474
$id = $this->normalizeIdentifiers($id, $manager, $resourceClass);
7575
}
7676
if (!\is_array($id)) {
77-
throw new \InvalidArgumentException(sprintf(
78-
'$id must be array when "%s" key is set to true in the $context',
79-
IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER
80-
));
77+
throw new \InvalidArgumentException(sprintf('$id must be array when "%s" key is set to true in the $context', IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER));
8178
}
8279
$identifiers = $id;
8380

0 commit comments

Comments
 (0)