From 17cfc4e592911e59bb1277f5ef4ac92cfa938c2a Mon Sep 17 00:00:00 2001 From: Ben Davies Date: Mon, 4 Nov 2019 12:25:05 +0000 Subject: [PATCH 01/12] GitHub Actions: cache composer dependencies --- .github/workflows/ci.yml | 124 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5b447cc3470..9feab98760d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -151,6 +159,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -243,6 +259,15 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-lowest-deps-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}-lowest-deps- + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -298,6 +323,15 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-lowest-deps-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}-lowest-deps- + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -380,6 +414,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -459,6 +501,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -541,6 +591,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -620,6 +678,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -698,6 +764,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -795,6 +869,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -903,6 +985,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -1002,6 +1092,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -1089,6 +1187,14 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -1147,6 +1253,15 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-symfony${{ matrix.symfony }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}-symfony${{ matrix.symfony }}- + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ @@ -1222,6 +1337,15 @@ jobs: run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - name: Install Composer run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet + - name: Cache Composer packages + uses: actions/cache@v1 + with: + path: ~/.composer/cache + key: composer-php${{ matrix.php }}-symfony${{ matrix.symfony }}-${{ github.sha }} + restore-keys: | + composer-php${{ matrix.php }}-symfony${{ matrix.symfony }}- + composer-php${{ matrix.php }}- + composer- - name: Install Symfony Flex run: | composer global require --prefer-dist --no-progress --no-suggest --ansi \ From 0ac7610035edd3085a335fc07fd4d4d8f2e9a362 Mon Sep 17 00:00:00 2001 From: Ben Davies Date: Wed, 13 Nov 2019 16:48:30 +0000 Subject: [PATCH 02/12] wided cached composer directories include cache-repo-dir in cache so dependency resolution is faster when running `composer update` see: https://getcomposer.org/doc/06-config.md#cache-repo-dir --- .circleci/config.yml | 4 ++-- .travis.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e4e2fc9c841..5787142ad1d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -59,12 +59,12 @@ commands: - save_cache: name: Save Composer cache paths: - - ~/.composer/cache/files + - ~/.composer/cache key: composer-cache-{{ .Branch }}-{{ .BuildNum }} - save_cache: name: Save Composer cache paths: - - ~/.composer/cache/files + - ~/.composer/cache key: composer-cache-{{ .Revision }}-{{ .BuildNum }} save-php-cs-fixer-cache: steps: diff --git a/.travis.yml b/.travis.yml index b284e3d06a7..f871e632877 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ env: cache: directories: - - $HOME/.composer/cache/files + - $HOME/.composer/cache - $HOME/.npm .steps: From b72a76e0d5f3177be502671d07f377f8e92396d5 Mon Sep 17 00:00:00 2001 From: ThomasLassalle <56689494+ThomasLassalle@users.noreply.github.com> Date: Thu, 14 Nov 2019 13:46:00 +0100 Subject: [PATCH 03/12] Fix ApiResource annotation : 'int' should be 'bool' (#3247) --- src/Annotation/ApiResource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Annotation/ApiResource.php b/src/Annotation/ApiResource.php index 267a17ad50f..a99cc4d0626 100644 --- a/src/Annotation/ApiResource.php +++ b/src/Annotation/ApiResource.php @@ -321,7 +321,7 @@ final class ApiResource * @see https://api-platform.com/docs/core/performance/#partial-pagination * @see https://github.com/Haehnchen/idea-php-annotation-plugin/issues/112 * - * @var int + * @var bool */ private $paginationPartial; From 5c6777241b6dd40c09ae6754a69f0980f11ebff5 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Thu, 14 Nov 2019 15:24:47 +0100 Subject: [PATCH 04/12] Fix PHPStan ignored error pattern (#3255) --- phpstan.neon.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 9724777af5d..b93a9de6a01 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -60,7 +60,7 @@ parameters: - message: '#Property ApiPlatform\\Core\\Test\\DoctrineMongoDbOdmFilterTestCase::\$repository \(Doctrine\\ODM\\MongoDB\\Repository\\DocumentRepository\) does not accept Doctrine\\ORM\\EntityRepository\.#' path: %currentWorkingDirectory%/src/Test/DoctrineMongoDbOdmFilterTestCase.php - - '#Method ApiPlatform\\Core\\(Serializer\\Abstract|JsonApi\\Serializer\\)ItemNormalizer::normalizeRelation\(\) should return array\|string but returns array\|bool\|float\|int\|string\.#' + - '#Method ApiPlatform\\Core\\(Serializer\\Abstract|JsonApi\\Serializer\\)ItemNormalizer::normalizeRelation\(\) should return array\|string but returns array\|bool\|float\|int\|string\|null\.#' - '#Method ApiPlatform\\Core\\Util\\RequestParser::parseRequestParams\(\) should return array but returns array\|false\.#' - message: '#Method ApiPlatform\\Core\\Bridge\\Doctrine\\Orm\\Util\\QueryBuilderHelper::mapJoinAliases() should return array\|string> but returns array\.#' From d5a222f38933e5a5132a2a222aa8b306e46b2cce Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 14 Nov 2019 17:31:14 +0100 Subject: [PATCH 05/12] Fix symfony/error-handler compatibility --- composer.json | 2 +- phpstan.neon.dist | 9 ++++----- src/Action/ExceptionAction.php | 2 +- src/Hydra/Serializer/ErrorNormalizer.php | 7 ++++--- src/JsonApi/Serializer/ErrorNormalizer.php | 7 ++++--- src/Problem/Serializer/ErrorNormalizer.php | 5 +++-- src/Problem/Serializer/ErrorNormalizerTrait.php | 5 +++-- tests/Fixtures/app/AppKernel.php | 8 ++++---- 8 files changed, 24 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index 57f9a704c3d..da717b51dae 100644 --- a/composer.json +++ b/composer.json @@ -66,7 +66,7 @@ "symfony/config": "^3.4 || ^4.0 || ^5.0", "symfony/console": "^3.4 || ^4.0 || ^5.0", "symfony/css-selector": "^3.4 || ^4.0 || ^5.0", - "symfony/debug": "^3.4 || ^4.0 || ^5.0", + "symfony/debug": "^3.4 || ^4.0", "symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0", "symfony/doctrine-bridge": "^3.4 || ^4.0 || ^5.0", "symfony/dom-crawler": "^3.4 || ^4.0 || ^5.0", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index b93a9de6a01..09a4a1e9382 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -109,11 +109,10 @@ parameters: # Expected, due to forward compatibility - - message: '#Class Symfony\\Component\\ErrorRenderer\\ErrorRenderer not found\.#' + message: '#Class Symfony\\Component\\ErrorHandler\\ErrorRenderer\\ErrorRendererInterface not found\.#' path: %currentWorkingDirectory%/tests/Fixtures/app/AppKernel.php - - message: '#Parameter \$exception of method ApiPlatform\\Core\\Action\\ExceptionAction::__invoke\(\) has invalid typehint type Symfony\\Component\\ErrorRenderer\\Exception\\FlattenException\.#' - path: %currentWorkingDirectory%/src/Action/ExceptionAction.php - - - message: '#Call to method get(Class|Headers|StatusCode)\(\) on an unknown class Symfony\\Component\\ErrorRenderer\\Exception\\FlattenException\.#' + message: '#Parameter \$exception of method ApiPlatform\\Core\\Action\\ExceptionAction::__invoke\(\) has invalid typehint type Symfony\\Component\\ErrorHandler\\Exception\\FlattenException\.#' path: %currentWorkingDirectory%/src/Action/ExceptionAction.php + - '#Call to method get(Class|Headers|StatusCode)\(\) on an unknown class Symfony\\Component\\ErrorHandler\\Exception\\FlattenException\.#' + - '#Class Symfony\\Component\\ErrorHandler\\Exception\\FlattenException not found\.#' diff --git a/src/Action/ExceptionAction.php b/src/Action/ExceptionAction.php index 0aec32a935c..8476c21bb9b 100644 --- a/src/Action/ExceptionAction.php +++ b/src/Action/ExceptionAction.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Util\ErrorFormatGuesser; use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException; -use Symfony\Component\ErrorRenderer\Exception\FlattenException; +use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Serializer\SerializerInterface; diff --git a/src/Hydra/Serializer/ErrorNormalizer.php b/src/Hydra/Serializer/ErrorNormalizer.php index ec6f9d8cca6..6aeee094142 100644 --- a/src/Hydra/Serializer/ErrorNormalizer.php +++ b/src/Hydra/Serializer/ErrorNormalizer.php @@ -15,12 +15,13 @@ use ApiPlatform\Core\Api\UrlGeneratorInterface; use ApiPlatform\Core\Problem\Serializer\ErrorNormalizerTrait; -use Symfony\Component\Debug\Exception\FlattenException; +use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException; +use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; /** - * Converts {@see \Exception} or {@see \Symfony\Component\Debug\Exception\FlattenException} to a Hydra error representation. + * Converts {@see \Exception} or {@see FlattenException} or {@see LegacyFlattenException} to a Hydra error representation. * * @author Kévin Dunglas * @author Samuel ROZE @@ -67,7 +68,7 @@ public function normalize($object, $format = null, array $context = []) */ public function supportsNormalization($data, $format = null) { - return self::FORMAT === $format && ($data instanceof \Exception || $data instanceof FlattenException); + return self::FORMAT === $format && ($data instanceof \Exception || $data instanceof FlattenException || $data instanceof LegacyFlattenException); } /** diff --git a/src/JsonApi/Serializer/ErrorNormalizer.php b/src/JsonApi/Serializer/ErrorNormalizer.php index 257b62c1e3d..618147b17ac 100644 --- a/src/JsonApi/Serializer/ErrorNormalizer.php +++ b/src/JsonApi/Serializer/ErrorNormalizer.php @@ -14,12 +14,13 @@ namespace ApiPlatform\Core\JsonApi\Serializer; use ApiPlatform\Core\Problem\Serializer\ErrorNormalizerTrait; -use Symfony\Component\Debug\Exception\FlattenException; +use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException; +use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; /** - * Converts {@see \Exception} or {@see \Symfony\Component\Debug\Exception\FlattenException} to a JSON API error representation. + * Converts {@see \Exception} or {@see FlattenException} or {@see LegacyFlattenException} to a JSON API error representation. * * @author Héctor Hurtarte */ @@ -60,7 +61,7 @@ public function normalize($object, $format = null, array $context = []) */ public function supportsNormalization($data, $format = null) { - return self::FORMAT === $format && ($data instanceof \Exception || $data instanceof FlattenException); + return self::FORMAT === $format && ($data instanceof \Exception || $data instanceof FlattenException || $data instanceof LegacyFlattenException); } /** diff --git a/src/Problem/Serializer/ErrorNormalizer.php b/src/Problem/Serializer/ErrorNormalizer.php index 4b208e57fe9..b79f8a02066 100644 --- a/src/Problem/Serializer/ErrorNormalizer.php +++ b/src/Problem/Serializer/ErrorNormalizer.php @@ -13,7 +13,8 @@ namespace ApiPlatform\Core\Problem\Serializer; -use Symfony\Component\Debug\Exception\FlattenException; +use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException; +use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -67,7 +68,7 @@ public function normalize($object, $format = null, array $context = []) */ public function supportsNormalization($data, $format = null) { - return self::FORMAT === $format && ($data instanceof \Exception || $data instanceof FlattenException); + return self::FORMAT === $format && ($data instanceof \Exception || $data instanceof FlattenException || $data instanceof LegacyFlattenException); } /** diff --git a/src/Problem/Serializer/ErrorNormalizerTrait.php b/src/Problem/Serializer/ErrorNormalizerTrait.php index 20ecd786572..cca553eb3c7 100644 --- a/src/Problem/Serializer/ErrorNormalizerTrait.php +++ b/src/Problem/Serializer/ErrorNormalizerTrait.php @@ -13,7 +13,8 @@ namespace ApiPlatform\Core\Problem\Serializer; -use Symfony\Component\Debug\Exception\FlattenException; +use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException; +use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\HttpFoundation\Response; trait ErrorNormalizerTrait @@ -26,7 +27,7 @@ private function getErrorMessage($object, array $context, bool $debug = false): return $message; } - if ($object instanceof FlattenException) { + if ($object instanceof FlattenException || $object instanceof LegacyFlattenException) { $statusCode = $context['statusCode'] ?? $object->getStatusCode(); if ($statusCode >= 500 && $statusCode < 600) { $message = Response::$statusTexts[$statusCode]; diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index bc4d14d590d..b6bc5193012 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -27,10 +27,10 @@ use Symfony\Bundle\WebProfilerBundle\WebProfilerBundle; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\ErrorRenderer\ErrorRenderer; +use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\RouteCollectionBuilder; -use Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder; +use Symfony\Component\Security\Core\Encoder\NativePasswordEncoder; use Symfony\Component\Security\Core\User\UserInterface; /** @@ -98,7 +98,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load $loader->load(__DIR__."/config/config_{$this->getEnvironment()}.yml"); - $alg = class_exists(SodiumPasswordEncoder::class) && SodiumPasswordEncoder::isSupported() ? 'auto' : 'bcrypt'; + $alg = class_exists(NativePasswordEncoder::class) ? 'auto' : 'bcrypt'; $securityConfig = [ 'encoders' => [ User::class => $alg, @@ -155,7 +155,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load } $twigConfig = ['strict_variables' => '%kernel.debug%']; - if (class_exists(ErrorRenderer::class)) { + if (interface_exists(ErrorRendererInterface::class)) { $twigConfig['exception_controller'] = null; } $c->prependExtensionConfig('twig', $twigConfig); From 79e2ff60c1c79f543d80d7ded3dc4c9b5f0493ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 15 Nov 2019 10:54:30 +0100 Subject: [PATCH 06/12] Prevent adding Link headers for CORS preflight requets --- .../EventListener/AddLinkHeaderListener.php | 16 ++++++--- .../EventListener/AddLinkHeaderListener.php | 18 +++++++--- src/Util/CorsTrait.php | 33 +++++++++++++++++++ .../AddLinkHeaderListenerTest.php | 16 +++++++++ .../AddLinkHeaderListenerTest.php | 16 +++++++++ 5 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 src/Util/CorsTrait.php diff --git a/src/Hydra/EventListener/AddLinkHeaderListener.php b/src/Hydra/EventListener/AddLinkHeaderListener.php index 0e42a7fd2cb..b208c01afff 100644 --- a/src/Hydra/EventListener/AddLinkHeaderListener.php +++ b/src/Hydra/EventListener/AddLinkHeaderListener.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Api\UrlGeneratorInterface; use ApiPlatform\Core\JsonLd\ContextBuilder; +use ApiPlatform\Core\Util\CorsTrait; use Fig\Link\GenericLinkProvider; use Fig\Link\Link; use Symfony\Component\HttpKernel\Event\ResponseEvent; @@ -26,6 +27,8 @@ */ final class AddLinkHeaderListener { + use CorsTrait; + private $urlGenerator; public function __construct(UrlGeneratorInterface $urlGenerator) @@ -38,15 +41,20 @@ public function __construct(UrlGeneratorInterface $urlGenerator) */ public function onKernelResponse(ResponseEvent $event): void { + $request = $event->getRequest(); + // Prevent issues with NelmioCorsBundle + if ($this->isPreflightRequest($request)) { + return; + } + $apiDocUrl = $this->urlGenerator->generate('api_doc', ['_format' => 'jsonld'], UrlGeneratorInterface::ABS_URL); $link = new Link(ContextBuilder::HYDRA_NS.'apiDocumentation', $apiDocUrl); - $attributes = $event->getRequest()->attributes; - if (null === $linkProvider = $attributes->get('_links')) { - $attributes->set('_links', new GenericLinkProvider([$link])); + if (null === $linkProvider = $request->attributes->get('_links')) { + $request->attributes->set('_links', new GenericLinkProvider([$link])); return; } - $attributes->set('_links', $linkProvider->withLink($link)); + $request->attributes->set('_links', $linkProvider->withLink($link)); } } diff --git a/src/Mercure/EventListener/AddLinkHeaderListener.php b/src/Mercure/EventListener/AddLinkHeaderListener.php index 12b83bbed28..024a92166b3 100644 --- a/src/Mercure/EventListener/AddLinkHeaderListener.php +++ b/src/Mercure/EventListener/AddLinkHeaderListener.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Mercure\EventListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Util\CorsTrait; use Fig\Link\GenericLinkProvider; use Fig\Link\Link; use Symfony\Component\HttpKernel\Event\ResponseEvent; @@ -25,6 +26,8 @@ */ final class AddLinkHeaderListener { + use CorsTrait; + private $resourceMetadataFactory; private $hub; @@ -39,22 +42,27 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa */ public function onKernelResponse(ResponseEvent $event): void { + $request = $event->getRequest(); + // Prevent issues with NelmioCorsBundle + if ($this->isPreflightRequest($request)) { + return; + } + $link = new Link('mercure', $this->hub); - $attributes = $event->getRequest()->attributes; if ( - null === ($resourceClass = $attributes->get('_api_resource_class')) || + null === ($resourceClass = $request->attributes->get('_api_resource_class')) || false === $this->resourceMetadataFactory->create($resourceClass)->getAttribute('mercure', false) ) { return; } - if (null === $linkProvider = $attributes->get('_links')) { - $attributes->set('_links', new GenericLinkProvider([$link])); + if (null === $linkProvider = $request->attributes->get('_links')) { + $request->attributes->set('_links', new GenericLinkProvider([$link])); return; } - $attributes->set('_links', $linkProvider->withLink($link)); + $request->attributes->set('_links', $linkProvider->withLink($link)); } } diff --git a/src/Util/CorsTrait.php b/src/Util/CorsTrait.php new file mode 100644 index 00000000000..e5f48925f21 --- /dev/null +++ b/src/Util/CorsTrait.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Core\Util; + +use Symfony\Component\HttpFoundation\Request; + +/** + * CORS utils. + * + * To be removed when https://github.com/symfony/symfony/pull/34391 wil be merged. + * + * @internal + * + * @author Kévin Dunglas + */ +trait CorsTrait +{ + public function isPreflightRequest(Request $request): bool + { + return $request->isMethod('OPTIONS') && $request->headers->has('Access-Control-Request-Method'); + } +} diff --git a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php index 193c5842bcf..4ab8f63a7fa 100644 --- a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php @@ -50,4 +50,20 @@ public function provider(): array ['; rel="mercure",; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"', new Request([], [], ['_links' => new GenericLinkProvider([new Link('mercure', 'https://demo.mercure.rocks/hub')])])], ]; } + + public function testSkipWhenPreflightRequest(): void + { + $request = new Request(); + $request->setMethod('OPTIONS'); + $request->headers->set('Access-Control-Request-Method', 'POST'); + + $event = $this->prophesize(ResponseEvent::class); + $event->getRequest()->willReturn($request)->shouldBeCalled(); + + $urlGenerator = $this->prophesize(UrlGeneratorInterface::class); + $listener = new AddLinkHeaderListener($urlGenerator->reveal()); + $listener->onKernelResponse($event->reveal()); + + $this->assertFalse($request->attributes->has('_links')); + } } diff --git a/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php b/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php index e56d25486e2..01739623029 100644 --- a/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php @@ -80,4 +80,20 @@ public function doNotAddProvider(): array [new Request([], [], ['_api_resource_class' => Dummy::class])], ]; } + + public function testSkipWhenPreflightRequest(): void + { + $request = new Request(); + $request->setMethod('OPTIONS'); + $request->headers->set('Access-Control-Request-Method', 'POST'); + + $event = $this->prophesize(ResponseEvent::class); + $event->getRequest()->willReturn($request)->shouldBeCalled(); + + $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); + $listener = new AddLinkHeaderListener($resourceMetadataFactory->reveal(), 'http://example.com/.well-known/mercure'); + $listener->onKernelResponse($event->reveal()); + + $this->assertFalse($request->attributes->has('_links')); + } } From 276f3c72ca8cca8d6ef789cbf01c163e0bc8977f Mon Sep 17 00:00:00 2001 From: Teoh Han Hui Date: Thu, 14 Nov 2019 15:50:56 +0100 Subject: [PATCH 07/12] Cache ext-mongodb build directory --- .circleci/config.yml | 149 ++++++++++--- .github/workflows/ci.yml | 439 +++++++++++++++++++++++++++++++++++---- .travis.yml | 2 +- 3 files changed, 522 insertions(+), 68 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5787142ad1d..a114feabe20 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,5 +1,8 @@ version: 2.1 +.constants: + - &ext-mongodb-version '1.6.0' + commands: clear-test-app-cache: steps: @@ -17,12 +20,35 @@ commands: name: Disable xdebug PHP extension command: sudo rm /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini install-mongodb-php-extension: + steps: + - install-php-extension-from-pecl: + extension_name: mongodb + extension_version: *ext-mongodb-version + install-php-extension-from-pecl: + parameters: + extension_name: + description: Name of the PHP extension. + type: string + extension_version: + description: Version of the PHP extension. + type: string steps: - run: - name: Install mongodb PHP extension + name: Install << parameters.extension_name >> PHP extension + environment: + BUILD_DIR: /var/tmp/build/ext-<< parameters.extension_name >>-<< parameters.extension_version >> + SRC_DIR: /usr/src/php/ext/<< parameters.extension_name >> command: | - sudo pecl install mongodb-1.5.5 - sudo docker-php-ext-enable mongodb + sudo mkdir -p "$SRC_DIR" "$BUILD_DIR" + sudo chown -R "$(id -u):$(id -g)" "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/<< parameters.extension_name >>-<< parameters.extension_version >>.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + sudo make -j"$(nproc)" install + sudo docker-php-ext-enable << parameters.extension_name >> install-symfony-flex: steps: - run: @@ -35,61 +61,114 @@ commands: - restore_cache: name: Restore Composer cache keys: - - composer-cache-{{ .Revision }} - - composer-cache-{{ .Branch }} - - composer-cache + - composer-{{ .Revision }} + - composer-{{ .Branch }} + - composer- + restore-mongodb-php-extension-build-cache: + parameters: + php_version: + description: PHP version (major.minor). + type: string + steps: + - restore-php-extension-build-cache: + extension_name: mongodb + extension_version: *ext-mongodb-version + php_version: << parameters.php_version >> restore-php-cs-fixer-cache: steps: - restore_cache: name: Restore PHP-CS-Fixer cache keys: - - php-cs-fixer-cache-{{ .Revision }} - - php-cs-fixer-cache-{{ .Branch }} - - php-cs-fixer-cache + - php-cs-fixer-{{ .Revision }} + - php-cs-fixer-{{ .Branch }} + - php-cs-fixer- + restore-php-extension-build-cache: + parameters: + extension_name: + description: Name of the PHP extension. + type: string + extension_version: + description: Version of the PHP extension. + type: string + php_version: + description: PHP version (major.minor). + type: string + steps: + - restore_cache: + name: Restore << parameters.extension_name >> PHP extension build cache + keys: + - ext-<< parameters.extension_name >>-<< parameters.extension_version >>-php<< parameters.php_version >>- restore-phpstan-cache: steps: - restore_cache: name: Restore PHPStan cache keys: - - phpstan-cache-{{ .Revision }} - - phpstan-cache-{{ .Branch }} - - phpstan-cache + - phpstan-{{ .Revision }} + - phpstan-{{ .Branch }} + - phpstan- save-composer-cache: steps: - save_cache: name: Save Composer cache paths: - ~/.composer/cache - key: composer-cache-{{ .Branch }}-{{ .BuildNum }} + key: composer-{{ .Branch }}-{{ .BuildNum }} - save_cache: name: Save Composer cache paths: - ~/.composer/cache - key: composer-cache-{{ .Revision }}-{{ .BuildNum }} + key: composer-{{ .Revision }}-{{ .BuildNum }} + save-mongodb-php-extension-build-cache: + parameters: + php_version: + description: PHP version (major.minor). + type: string + steps: + - save-php-extension-build-cache: + extension_name: mongodb + extension_version: *ext-mongodb-version + php_version: << parameters.php_version >> save-php-cs-fixer-cache: steps: - save_cache: name: Save PHP-CS-Fixer cache paths: - .php_cs.cache - key: php-cs-fixer-cache-{{ .Branch }}-{{ .BuildNum }} + key: php-cs-fixer-{{ .Branch }}-{{ .BuildNum }} - save_cache: name: Save PHP-CS-Fixer cache paths: - .php_cs.cache - key: php-cs-fixer-cache-{{ .Revision }}-{{ .BuildNum }} + key: php-cs-fixer-{{ .Revision }}-{{ .BuildNum }} + save-php-extension-build-cache: + parameters: + extension_name: + description: Name of the PHP extension. + type: string + extension_version: + description: Version of the PHP extension. + type: string + php_version: + description: PHP version (major.minor). + type: string + steps: + - save_cache: + name: Save << parameters.extension_name >> PHP extension build cache + paths: + - /var/tmp/build/ext-<< parameters.extension_name >>-<< parameters.extension_version >> + key: ext-<< parameters.extension_name >>-<< parameters.extension_version >>-php<< parameters.php_version >>-{{ .BuildNum }} save-phpstan-cache: steps: - save_cache: name: Save PHPStan cache paths: - /tmp/phpstan/cache - key: phpstan-cache-{{ .Branch }}-{{ .BuildNum }} + key: phpstan-{{ .Branch }}-{{ .BuildNum }} - save_cache: name: Save PHPStan cache paths: - /tmp/phpstan/cache - key: phpstan-cache-{{ .Revision }}-{{ .BuildNum }} + key: phpstan-{{ .Revision }}-{{ .BuildNum }} update-project-dependencies: steps: - run: @@ -98,15 +177,25 @@ commands: executors: php: + parameters: + php_version: + description: PHP version (major.minor). + type: string docker: - - image: circleci/php:7.3-node + - image: circleci/php:<< parameters.php_version >>-node environment: - SYMFONY_REQUIRE: ^3.4 || ^4.0 + SYMFONY_REQUIRE: ^3.4 || ^4.0 || ^5.0 jobs: php-cs-fixer: description: PHP-CS-Fixer - executor: php + parameters: + php_version: + description: PHP version (major.minor). + type: string + executor: + name: php + php_version: << parameters.php_version >> environment: PHP_CS_FIXER_FUTURE_MODE: '1' working_directory: ~/api-platform/core @@ -132,13 +221,23 @@ jobs: phpstan: description: PHPStan - executor: php + parameters: + php_version: + description: PHP version (major.minor). + type: string + executor: + name: php + php_version: << parameters.php_version >> environment: APP_DEBUG: '1' # https://github.com/phpstan/phpstan-symfony/issues/37 working_directory: ~/api-platform/core steps: - checkout + - restore-mongodb-php-extension-build-cache: + php_version: << parameters.php_version >> - install-mongodb-php-extension + - save-mongodb-php-extension-build-cache: + php_version: << parameters.php_version >> - disable-xdebug-php-extension - disable-php-memory-limit - restore-composer-cache @@ -156,5 +255,7 @@ workflows: version: 2 lint: jobs: - - php-cs-fixer - - phpstan + - php-cs-fixer: + php_version: '7.3' + - phpstan: + php_version: '7.3' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9feab98760d..caf391096fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ env: COMPOSER_ALLOW_SUPERUSER: '1' # https://getcomposer.org/doc/03-cli.md#composer-allow-superuser COMPOSER_INSTALLER_COMMIT: fb22b78362d31c0d2bf516d1f8cdfd2745caa431 COVERAGE: '0' - EXT_MONGODB_VERSION: '1.5.5' + EXT_MONGODB_VERSION: '1.6.0' EXT_PCOV_VERSION: '1.0.6' LEGACY: '0' SYMFONY_REQUIRE: ^3.4 || ^4.0 || ^5.0 @@ -21,6 +21,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec strategy: matrix: php: @@ -40,17 +41,47 @@ jobs: run: | apk add \ unzip \ + - name: Cache mongodb PHP extension build + if: (!startsWith(matrix.php, '7.1')) + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension if: (!startsWith(matrix.php, '7.1')) + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Install pcov PHP extension if: matrix.coverage + env: + BUILD_DIR: /var/tmp/build/ext-pcov-${{ env.EXT_PCOV_VERSION }} + SRC_DIR: /usr/src/php/ext/pcov run: | - apk add $PHPIZE_DEPS - pecl install pcov-$EXT_PCOV_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/pcov-$EXT_PCOV_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable pcov - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -124,6 +155,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec strategy: matrix: php: @@ -143,17 +175,47 @@ jobs: run: | apk add \ unzip \ + - name: Cache mongodb PHP extension build + if: (!startsWith(matrix.php, '7.1')) + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension if: (!startsWith(matrix.php, '7.1')) + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Install pcov PHP extension if: matrix.coverage + env: + BUILD_DIR: /var/tmp/build/ext-pcov-${{ env.EXT_PCOV_VERSION }} + SRC_DIR: /usr/src/php/ext/pcov run: | - apk add $PHPIZE_DEPS - pecl install pcov-$EXT_PCOV_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/pcov-$EXT_PCOV_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable pcov - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -236,6 +298,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec strategy: matrix: php: @@ -250,10 +313,28 @@ jobs: run: | apk add \ unzip \ + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -300,6 +381,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec strategy: matrix: php: @@ -314,10 +396,28 @@ jobs: run: | apk add \ unzip \ + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -367,6 +467,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec services: postgres: image: postgres:10-alpine @@ -405,10 +506,28 @@ jobs: docker-php-ext-install -j$(nproc) \ pdo_pgsql \ ; + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -454,6 +573,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec services: postgres: image: postgres:10-alpine @@ -492,10 +612,28 @@ jobs: docker-php-ext-install -j$(nproc) \ pdo_pgsql \ ; + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -544,6 +682,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec services: mysql: image: mysql:5.7 @@ -582,10 +721,28 @@ jobs: docker-php-ext-install -j$(nproc) \ pdo_mysql \ ; + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -631,6 +788,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec services: mysql: image: mysql:5.7 @@ -669,10 +827,28 @@ jobs: docker-php-ext-install -j$(nproc) \ pdo_mysql \ ; + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -721,6 +897,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec services: mongo: image: mongo:4 @@ -749,16 +926,45 @@ jobs: run: | apk add \ unzip \ + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Install pcov PHP extension if: matrix.coverage + env: + BUILD_DIR: /var/tmp/build/ext-pcov-${{ env.EXT_PCOV_VERSION }} + SRC_DIR: /usr/src/php/ext/pcov run: | - apk add $PHPIZE_DEPS - pecl install pcov-$EXT_PCOV_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/pcov-$EXT_PCOV_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable pcov - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -826,6 +1032,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec services: mongo: image: mongo:4 @@ -854,16 +1061,45 @@ jobs: run: | apk add \ unzip \ + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Install pcov PHP extension if: matrix.coverage + env: + BUILD_DIR: /var/tmp/build/ext-pcov-${{ env.EXT_PCOV_VERSION }} + SRC_DIR: /usr/src/php/ext/pcov run: | - apk add $PHPIZE_DEPS - pecl install pcov-$EXT_PCOV_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/pcov-$EXT_PCOV_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable pcov - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -940,6 +1176,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:6.8.3 # https://github.com/elastic/elasticsearch/issues/43627 @@ -970,16 +1207,45 @@ jobs: run: | apk add \ unzip \ + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Install pcov PHP extension if: matrix.coverage + env: + BUILD_DIR: /var/tmp/build/ext-pcov-${{ env.EXT_PCOV_VERSION }} + SRC_DIR: /usr/src/php/ext/pcov run: | - apk add $PHPIZE_DEPS - pecl install pcov-$EXT_PCOV_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/pcov-$EXT_PCOV_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable pcov - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -1047,6 +1313,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:6.8.3 # https://github.com/elastic/elasticsearch/issues/43627 @@ -1077,16 +1344,45 @@ jobs: run: | apk add \ unzip \ + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Install pcov PHP extension if: matrix.coverage + env: + BUILD_DIR: /var/tmp/build/ext-pcov-${{ env.EXT_PCOV_VERSION }} + SRC_DIR: /usr/src/php/ext/pcov run: | - apk add $PHPIZE_DEPS - pecl install pcov-$EXT_PCOV_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/pcov-$EXT_PCOV_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable pcov - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -1163,6 +1459,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec strategy: matrix: php: @@ -1178,10 +1475,28 @@ jobs: run: | apk add \ unzip \ + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -1227,6 +1542,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec strategy: matrix: php: @@ -1244,10 +1560,28 @@ jobs: jq \ moreutils \ unzip \ + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini @@ -1311,6 +1645,7 @@ jobs: image: php:${{ matrix.php }}-alpine options: >- --tmpfs /tmp:exec + --tmpfs /var/tmp:exec strategy: matrix: php: @@ -1328,10 +1663,28 @@ jobs: jq \ moreutils \ unzip \ + - name: Cache mongodb PHP extension build + uses: actions/cache@v1 + with: + path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} + restore-keys: | + ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - name: Install mongodb PHP extension + env: + BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} + SRC_DIR: /usr/src/php/ext/mongodb run: | - apk add $PHPIZE_DEPS - pecl install mongodb-$EXT_MONGODB_VERSION + apk add \ + $PHPIZE_DEPS + mkdir -p "$SRC_DIR" "$BUILD_DIR" + cd "$SRC_DIR" + curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 + phpize + cd "$BUILD_DIR" + "$SRC_DIR"/configure --config-cache + make -j"$(nproc)" + make -j"$(nproc)" install docker-php-ext-enable mongodb - name: Disable PHP memory limit run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini diff --git a/.travis.yml b/.travis.yml index f871e632877..2c4ddfc79f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: php env: global: - - SYMFONY_REQUIRE='^3.4 || ^4.0' + - SYMFONY_REQUIRE='^3.4 || ^4.0 || ^5.0' cache: directories: From beea32b679ebe41d9320b3037d04ce9d7bbd7aeb Mon Sep 17 00:00:00 2001 From: Teoh Han Hui Date: Wed, 30 Oct 2019 12:29:30 +0100 Subject: [PATCH 08/12] Ensure correct return type from AbstractItemNormalizer::normalizeRelation --- phpstan.neon.dist | 9 ++++++- src/JsonApi/Serializer/ItemNormalizer.php | 30 +++++++++-------------- src/Serializer/AbstractItemNormalizer.php | 30 ++++++++++++++++++++--- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 09a4a1e9382..3c89465468a 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -25,6 +25,9 @@ parameters: path: %currentWorkingDirectory%/src/Identifier/Normalizer/IntegerDenormalizer.php # False positives + - + message: '#Variable \$iri might not be defined\.#' + path: %currentWorkingDirectory%/src/JsonApi/Serializer/ItemNormalizer.php - message: '#Variable \$positionPm might not be defined\.#' path: %currentWorkingDirectory%/src/Util/ClassInfoTrait.php @@ -60,7 +63,6 @@ parameters: - message: '#Property ApiPlatform\\Core\\Test\\DoctrineMongoDbOdmFilterTestCase::\$repository \(Doctrine\\ODM\\MongoDB\\Repository\\DocumentRepository\) does not accept Doctrine\\ORM\\EntityRepository\.#' path: %currentWorkingDirectory%/src/Test/DoctrineMongoDbOdmFilterTestCase.php - - '#Method ApiPlatform\\Core\\(Serializer\\Abstract|JsonApi\\Serializer\\)ItemNormalizer::normalizeRelation\(\) should return array\|string but returns array\|bool\|float\|int\|string\|null\.#' - '#Method ApiPlatform\\Core\\Util\\RequestParser::parseRequestParams\(\) should return array but returns array\|false\.#' - message: '#Method ApiPlatform\\Core\\Bridge\\Doctrine\\Orm\\Util\\QueryBuilderHelper::mapJoinAliases() should return array\|string> but returns array\.#' @@ -116,3 +118,8 @@ parameters: path: %currentWorkingDirectory%/src/Action/ExceptionAction.php - '#Call to method get(Class|Headers|StatusCode)\(\) on an unknown class Symfony\\Component\\ErrorHandler\\Exception\\FlattenException\.#' - '#Class Symfony\\Component\\ErrorHandler\\Exception\\FlattenException not found\.#' + - + message: '#Instanceof between bool\|float\|int|null and ArrayObject will always evaluate to false\.#' + paths: + - %currentWorkingDirectory%/src/JsonApi/Serializer/ItemNormalizer.php + - %currentWorkingDirectory%/src/Serializer/AbstractItemNormalizer.php diff --git a/src/JsonApi/Serializer/ItemNormalizer.php b/src/JsonApi/Serializer/ItemNormalizer.php index 448235c9eb0..ca869d67f0b 100644 --- a/src/JsonApi/Serializer/ItemNormalizer.php +++ b/src/JsonApi/Serializer/ItemNormalizer.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Core\JsonApi\Serializer; use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Api\OperationType; use ApiPlatform\Core\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Exception\ItemNotFoundException; use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; @@ -199,34 +198,29 @@ protected function denormalizeRelation(string $attributeName, PropertyMetadata $ * {@inheritdoc} * * @see http://jsonapi.org/format/#document-resource-object-linkage - * - * @throws LogicException */ protected function normalizeRelation(PropertyMetadata $propertyMetadata, $relatedObject, string $resourceClass, ?string $format, array $context) { - if (null === $relatedObject) { - if (isset($context['operation_type'], $context['subresource_resources'][$resourceClass]) && OperationType::SUBRESOURCE === $context['operation_type']) { - $iri = $this->iriConverter->getItemIriFromResourceClass($resourceClass, $context['subresource_resources'][$resourceClass]); - } else { - if ($this->serializer instanceof NormalizerInterface) { - return $this->serializer->normalize($relatedObject, $format, $context); - } - throw new LogicException(sprintf('The injected serializer must be an instance of "%s".', NormalizerInterface::class)); - } - } else { + if (null !== $relatedObject) { $iri = $this->iriConverter->getIriFromItem($relatedObject); $context['iri'] = $iri; if (isset($context['resources'])) { $context['resources'][$iri] = $iri; } - if (isset($context['api_included'])) { - if (!$this->serializer instanceof NormalizerInterface) { - throw new LogicException(sprintf('The injected serializer must be an instance of "%s".', NormalizerInterface::class)); - } + } - return $this->serializer->normalize($relatedObject, $format, $context); + if (null === $relatedObject || isset($context['api_included'])) { + if (!$this->serializer instanceof NormalizerInterface) { + throw new LogicException(sprintf('The injected serializer must be an instance of "%s".', NormalizerInterface::class)); } + + $normalizedRelatedObject = $this->serializer->normalize($relatedObject, $format, $context); + if (!\is_string($normalizedRelatedObject) && !\is_array($normalizedRelatedObject) && !$normalizedRelatedObject instanceof \ArrayObject && null !== $normalizedRelatedObject) { + throw new UnexpectedValueException('Expected normalized relation to be an IRI, array, \ArrayObject or null'); + } + + return $normalizedRelatedObject; } return [ diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index 932c5ed9efc..8c887dbcce3 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -495,6 +495,7 @@ protected function createRelationSerializationContext(string $resourceClass, arr * {@inheritdoc} * * @throws NoSuchPropertyException + * @throws UnexpectedValueException * @throws LogicException */ protected function getAttributeValue($object, $attribute, $format = null, array $context = []) @@ -515,13 +516,16 @@ protected function getAttributeValue($object, $attribute, $format = null, array $type = $propertyMetadata->getType(); if ( - is_iterable($attributeValue) && $type && $type->isCollection() && ($collectionValueType = $type->getCollectionValueType()) && ($className = $collectionValueType->getClassName()) && $this->resourceClassResolver->isResourceClass($className) ) { + if (!is_iterable($attributeValue)) { + throw new UnexpectedValueException('Unexpected non-iterable value for to-many relation.'); + } + $resourceClass = $this->resourceClassResolver->getResourceClass($attributeValue, $className); $childContext = $this->createChildContext($context, $attribute, $format); $childContext['resource_class'] = $resourceClass; @@ -535,6 +539,10 @@ protected function getAttributeValue($object, $attribute, $format = null, array ($className = $type->getClassName()) && $this->resourceClassResolver->isResourceClass($className) ) { + if (!\is_object($attributeValue) && null !== $attributeValue) { + throw new UnexpectedValueException('Unexpected non-object value for to-one relation.'); + } + $resourceClass = $this->resourceClassResolver->getResourceClass($attributeValue, $className); $childContext = $this->createChildContext($context, $attribute, $format); $childContext['resource_class'] = $resourceClass; @@ -556,11 +564,17 @@ protected function getAttributeValue($object, $attribute, $format = null, array * Normalizes a collection of relations (to-many). * * @param iterable $attributeValue + * + * @throws UnexpectedValueException */ protected function normalizeCollectionOfRelations(PropertyMetadata $propertyMetadata, $attributeValue, string $resourceClass, ?string $format, array $context): array { $value = []; foreach ($attributeValue as $index => $obj) { + if (!\is_object($obj) && null !== $obj) { + throw new UnexpectedValueException('Unexpected non-object element in to-many relation.'); + } + $value[$index] = $this->normalizeRelation($propertyMetadata, $obj, $resourceClass, $format, $context); } @@ -568,11 +582,14 @@ protected function normalizeCollectionOfRelations(PropertyMetadata $propertyMeta } /** - * Normalizes a relation as an object if is a Link or as an URI. + * Normalizes a relation. + * + * @param object|null $relatedObject * * @throws LogicException + * @throws UnexpectedValueException * - * @return string|array + * @return string|array|\ArrayObject|null IRI or normalized object data */ protected function normalizeRelation(PropertyMetadata $propertyMetadata, $relatedObject, string $resourceClass, ?string $format, array $context) { @@ -581,7 +598,12 @@ protected function normalizeRelation(PropertyMetadata $propertyMetadata, $relate throw new LogicException(sprintf('The injected serializer must be an instance of "%s".', NormalizerInterface::class)); } - return $this->serializer->normalize($relatedObject, $format, $context); + $normalizedRelatedObject = $this->serializer->normalize($relatedObject, $format, $context); + if (!\is_string($normalizedRelatedObject) && !\is_array($normalizedRelatedObject) && !$normalizedRelatedObject instanceof \ArrayObject && null !== $normalizedRelatedObject) { + throw new UnexpectedValueException('Expected normalized relation to be an IRI, array, \ArrayObject or null'); + } + + return $normalizedRelatedObject; } $iri = $this->iriConverter->getIriFromItem($relatedObject); From 788f203ad034f037cd3df2637879bc8d3ca5c866 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 12 Nov 2019 17:07:57 +0100 Subject: [PATCH 09/12] fix compat with Symfony 5 --- phpstan.neon.dist | 2 ++ .../EventListener/ValidationExceptionListener.php | 2 +- src/EventListener/ExceptionListener.php | 7 ++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 3c89465468a..8961542c8ff 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -116,6 +116,7 @@ parameters: - message: '#Parameter \$exception of method ApiPlatform\\Core\\Action\\ExceptionAction::__invoke\(\) has invalid typehint type Symfony\\Component\\ErrorHandler\\Exception\\FlattenException\.#' path: %currentWorkingDirectory%/src/Action/ExceptionAction.php + - '#Call to method get(Class|Headers|StatusCode)\(\) on an unknown class Symfony\\Component\\ErrorHandler\\Exception\\FlattenException\.#' - '#Class Symfony\\Component\\ErrorHandler\\Exception\\FlattenException not found\.#' - @@ -123,3 +124,4 @@ parameters: paths: - %currentWorkingDirectory%/src/JsonApi/Serializer/ItemNormalizer.php - %currentWorkingDirectory%/src/Serializer/AbstractItemNormalizer.php + - '#Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener#' diff --git a/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php b/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php index c332aa49014..7d9e45cd348 100644 --- a/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php +++ b/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php @@ -40,7 +40,7 @@ public function __construct(SerializerInterface $serializer, array $errorFormats */ public function onKernelException(ExceptionEvent $event): void { - $exception = $event->getException(); + $exception = method_exists($event, 'getThrowable') ? $event->getThrowable() : $event->getException(); if (!$exception instanceof ValidationException) { return; } diff --git a/src/EventListener/ExceptionListener.php b/src/EventListener/ExceptionListener.php index d87f0ddc894..094093800b6 100644 --- a/src/EventListener/ExceptionListener.php +++ b/src/EventListener/ExceptionListener.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\Util\RequestAttributesExtractor; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\EventListener\ErrorListener; use Symfony\Component\HttpKernel\EventListener\ExceptionListener as BaseExceptionListener; /** @@ -30,7 +31,11 @@ final class ExceptionListener public function __construct($controller, LoggerInterface $logger = null, $debug = false) { - $this->exceptionListener = new BaseExceptionListener($controller, $logger, $debug); + if (class_exists(ErrorListener::class)) { + $this->exceptionListener = new ErrorListener($controller, $logger, $debug); + } else { + $this->exceptionListener = new BaseExceptionListener($controller, $logger, $debug); + } } public function onKernelException(ExceptionEvent $event): void From ca9a55168de8526a661a0de03dbdd9c29080ba2f Mon Sep 17 00:00:00 2001 From: Flug Date: Fri, 15 Nov 2019 11:03:42 +0100 Subject: [PATCH 10/12] fix tests --- .../ValidationExceptionListenerTest.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php index 4d95e012500..85951e69a16 100644 --- a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php +++ b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php @@ -31,7 +31,11 @@ class ValidationExceptionListenerTest extends TestCase public function testNotValidationException() { $eventProphecy = $this->prophesize(ExceptionEvent::class); - $eventProphecy->getException()->willReturn(new \Exception())->shouldBeCalled(); + if(method_exists(ExceptionEvent::class, 'getException')){ + $eventProphecy->getException()->willReturn(new \Exception())->shouldBeCalled(); + }else { + $eventProphecy->getThrowable()->willReturn(new \Exception())->shouldBeCalled(); + } $eventProphecy->setResponse()->shouldNotBeCalled(); $serializerProphecy = $this->prophesize(SerializerInterface::class); @@ -46,7 +50,11 @@ public function testValidationException() $list = new ConstraintViolationList([]); $eventProphecy = $this->prophesize(ExceptionEvent::class); - $eventProphecy->getException()->willReturn(new ValidationException($list))->shouldBeCalled(); + if(method_exists(ExceptionEvent::class, 'getException')){ + $eventProphecy->getException()->willReturn(new ValidationException($list))->shouldBeCalled(); + }else { + $eventProphecy->getThrowable()->willReturn(new ValidationException($list))->shouldBeCalled(); + } $eventProphecy->getRequest()->willReturn(new Request())->shouldBeCalled(); $eventProphecy->setResponse(Argument::allOf( Argument::type(Response::class), From 77f16b553166c9dd17f49b3a766a6ea1a0e71e2f Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 15 Nov 2019 11:14:42 +0100 Subject: [PATCH 11/12] fix cs --- phpstan.neon.dist | 15 +++++++++++---- .../ValidationExceptionListenerTest.php | 8 ++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 8961542c8ff..123c541fb19 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -89,7 +89,7 @@ parameters: path: %currentWorkingDirectory%/src/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php - message: '#Service "api_platform.iri_converter" is private\.#' - path: %currentWorkingDirectory%/src/Bridge/Symfony/Bundle/Test/ApiTestCase.php + path: %currentWorkingDirectory%/src/Bridge/Symfony/Bundle/Test/ApiTestCase.php # Expected, due to optional interfaces - '#Method ApiPlatform\\Core\\Bridge\\Doctrine\\Orm\\Extension\\QueryCollectionExtensionInterface::applyToCollection\(\) invoked with 5 parameters, 3-4 required\.#' @@ -113,15 +113,22 @@ parameters: - message: '#Class Symfony\\Component\\ErrorHandler\\ErrorRenderer\\ErrorRendererInterface not found\.#' path: %currentWorkingDirectory%/tests/Fixtures/app/AppKernel.php + - '#Class Symfony\\Component\\ErrorHandler\\Exception\\FlattenException not found\.#' + - + message: '#Class Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener not found\.#' + path: %currentWorkingDirectory%/src/EventListener/ExceptionListener.php + - + message: '#Instantiated class Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener not found\.#' + path: %currentWorkingDirectory%/src/EventListener/ExceptionListener.php - message: '#Parameter \$exception of method ApiPlatform\\Core\\Action\\ExceptionAction::__invoke\(\) has invalid typehint type Symfony\\Component\\ErrorHandler\\Exception\\FlattenException\.#' path: %currentWorkingDirectory%/src/Action/ExceptionAction.php - - '#Call to method get(Class|Headers|StatusCode)\(\) on an unknown class Symfony\\Component\\ErrorHandler\\Exception\\FlattenException\.#' - - '#Class Symfony\\Component\\ErrorHandler\\Exception\\FlattenException not found\.#' + - + message: "#Call to function method_exists\\(\\) with 'Symfony\\\\\\\\Component.+' and 'getException' will always evaluate to false\\.#" + path: %currentWorkingDirectory%/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php - message: '#Instanceof between bool\|float\|int|null and ArrayObject will always evaluate to false\.#' paths: - %currentWorkingDirectory%/src/JsonApi/Serializer/ItemNormalizer.php - %currentWorkingDirectory%/src/Serializer/AbstractItemNormalizer.php - - '#Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener#' diff --git a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php index 85951e69a16..50f00beb951 100644 --- a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php +++ b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php @@ -31,9 +31,9 @@ class ValidationExceptionListenerTest extends TestCase public function testNotValidationException() { $eventProphecy = $this->prophesize(ExceptionEvent::class); - if(method_exists(ExceptionEvent::class, 'getException')){ + if (method_exists(ExceptionEvent::class, 'getException')) { $eventProphecy->getException()->willReturn(new \Exception())->shouldBeCalled(); - }else { + } else { $eventProphecy->getThrowable()->willReturn(new \Exception())->shouldBeCalled(); } $eventProphecy->setResponse()->shouldNotBeCalled(); @@ -50,9 +50,9 @@ public function testValidationException() $list = new ConstraintViolationList([]); $eventProphecy = $this->prophesize(ExceptionEvent::class); - if(method_exists(ExceptionEvent::class, 'getException')){ + if (method_exists(ExceptionEvent::class, 'getException')) { $eventProphecy->getException()->willReturn(new ValidationException($list))->shouldBeCalled(); - }else { + } else { $eventProphecy->getThrowable()->willReturn(new ValidationException($list))->shouldBeCalled(); } $eventProphecy->getRequest()->willReturn(new Request())->shouldBeCalled(); From 980db8af0ceede8a0a36f57485dcdb33bdcd8e2b Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 15 Nov 2019 14:51:08 +0100 Subject: [PATCH 12/12] Fix tests --- phpstan.neon.dist | 6 ++++-- .../ValidationExceptionListenerTest.php | 12 ++++++------ tests/EventListener/ExceptionListenerTest.php | 6 +++++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 123c541fb19..c753f581c86 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -125,8 +125,10 @@ parameters: path: %currentWorkingDirectory%/src/Action/ExceptionAction.php - '#Call to method get(Class|Headers|StatusCode)\(\) on an unknown class Symfony\\Component\\ErrorHandler\\Exception\\FlattenException\.#' - - message: "#Call to function method_exists\\(\\) with 'Symfony\\\\\\\\Component.+' and 'getException' will always evaluate to false\\.#" - path: %currentWorkingDirectory%/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php + message: "#Call to function method_exists\\(\\) with 'Symfony\\\\\\\\Component.+' and 'getThrowable' will always evaluate to false\\.#" + paths: + - %currentWorkingDirectory%/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php + - %currentWorkingDirectory%/tests/EventListener/ExceptionListenerTest.php - message: '#Instanceof between bool\|float\|int|null and ArrayObject will always evaluate to false\.#' paths: diff --git a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php index 50f00beb951..87ecb42cef2 100644 --- a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php +++ b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php @@ -31,10 +31,10 @@ class ValidationExceptionListenerTest extends TestCase public function testNotValidationException() { $eventProphecy = $this->prophesize(ExceptionEvent::class); - if (method_exists(ExceptionEvent::class, 'getException')) { - $eventProphecy->getException()->willReturn(new \Exception())->shouldBeCalled(); - } else { + if (method_exists(ExceptionEvent::class, 'getThrowable')) { $eventProphecy->getThrowable()->willReturn(new \Exception())->shouldBeCalled(); + } else { + $eventProphecy->getException()->willReturn(new \Exception())->shouldBeCalled(); } $eventProphecy->setResponse()->shouldNotBeCalled(); @@ -50,10 +50,10 @@ public function testValidationException() $list = new ConstraintViolationList([]); $eventProphecy = $this->prophesize(ExceptionEvent::class); - if (method_exists(ExceptionEvent::class, 'getException')) { - $eventProphecy->getException()->willReturn(new ValidationException($list))->shouldBeCalled(); - } else { + if (method_exists(ExceptionEvent::class, 'getThrowable')) { $eventProphecy->getThrowable()->willReturn(new ValidationException($list))->shouldBeCalled(); + } else { + $eventProphecy->getException()->willReturn(new ValidationException($list))->shouldBeCalled(); } $eventProphecy->getRequest()->willReturn(new Request())->shouldBeCalled(); $eventProphecy->setResponse(Argument::allOf( diff --git a/tests/EventListener/ExceptionListenerTest.php b/tests/EventListener/ExceptionListenerTest.php index 82b2afd19f7..5afe8030bdc 100644 --- a/tests/EventListener/ExceptionListenerTest.php +++ b/tests/EventListener/ExceptionListenerTest.php @@ -36,7 +36,11 @@ public function testOnKernelException(Request $request) $eventProphecy = $this->prophesize(ExceptionEvent::class); $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->getException()->willReturn(new \Exception()); + if (method_exists(ExceptionEvent::class, 'getThrowable')) { + $eventProphecy->getThrowable()->willReturn(new \Exception()); + } else { + $eventProphecy->getException()->willReturn(new \Exception()); + } $eventProphecy->getKernel()->willReturn($kernel); $eventProphecy->setResponse(Argument::type(Response::class))->shouldBeCalled();