Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
fcf3151
test(graphql): cover nested input without related mutation (#8629)
soyuka Oct 2, 2026
b10e80f
fix(symfony): check HttpClientTrait before loading the test client (#…
aleksejs1 Oct 2, 2026
5cd0a87
doc: describe the types listed by Symfony's debug:autowiring command …
nicolas-grekas Oct 5, 2026
c3eabbb
fix(symfony): hides the "Other API docs" label when there is only a s…
bram123 Oct 5, 2026
454262b
fix(symfony): avoid deprecated translation command probe (#8627)
tacman Oct 5, 2026
56c0be2
revert(openapi): array query params bracket notation (#8637)
soyuka Oct 5, 2026
b6555c8
fix(laravel): ignore invalid range filter values (#8632)
NotAFlightRisk Oct 6, 2026
88fab3b
fix(openapi): don't suffix [] on bracketed array keys (#8636)
soyuka Oct 6, 2026
ce64745
fix(serializer): Catch MissingConstructorArgumentsException (#8659)
bram123 Oct 9, 2026
3779894
fix(hal): use spl_object_id() for circular reference counters (#8657)
dualfroz Oct 9, 2026
ff1bfbd
fix(metadata): do not mutate parameters shared between operations (#8…
Maxcastel Oct 9, 2026
1335871
fix(hydra): handle string and null serialization groups in Documentat…
Roemerdt Oct 9, 2026
13a9c11
fix(doctrine): avoid more deprecation from doctrine
VincentLanglet Oct 9, 2026
5fcc64d
chore: suggest ext-deepclone (#8658)
soyuka Oct 9, 2026
3da7496
doc: changelog 4.4.4
soyuka Oct 9, 2026
d4b70d3
Merge remote-tracking branch 'upstream/4.4' into 5.0
soyuka Oct 9, 2026
9bdc340
doc: changelog 5.0.3
soyuka Oct 9, 2026
5e2db9a
fix(metadata): infer schema for Link URI variables from linked property
bram123 Oct 11, 2026
1b1308e
fix(metadata): fix LinkFactory phpcs issue and UriTemplateResourceMet…
bram123 Oct 11, 2026
a6e089c
test(graphql): cover nested input without related mutation (#8629)
soyuka Oct 2, 2026
cfacdb1
fix(symfony): check HttpClientTrait before loading the test client (#…
aleksejs1 Oct 2, 2026
6a0063a
doc: describe the types listed by Symfony's debug:autowiring command …
nicolas-grekas Oct 5, 2026
193d083
fix(symfony): hides the "Other API docs" label when there is only a s…
bram123 Oct 5, 2026
546527f
fix(serializer): Catch MissingConstructorArgumentsException (#8659)
bram123 Oct 9, 2026
cc0823c
fix(hal): use spl_object_id() for circular reference counters (#8657)
dualfroz Oct 9, 2026
c07185e
fix(metadata): do not mutate parameters shared between operations (#8…
Maxcastel Oct 9, 2026
24c1c1f
fix(doctrine): avoid more deprecation from doctrine
VincentLanglet Oct 9, 2026
e96d91a
chore: suggest ext-deepclone (#8658)
soyuka Oct 9, 2026
0460236
fix(symfony): avoid deprecated translation command probe (#8627)
tacman Oct 5, 2026
5a68eda
fix(laravel): ignore invalid range filter values (#8632)
NotAFlightRisk Oct 6, 2026
897ece3
fix(hydra): handle string and null serialization groups in Documentat…
Roemerdt Oct 9, 2026
ce8c6f1
doc: changelog 5.0.3
soyuka Oct 9, 2026
9bc9540
fix(metadata): infer schema for Link URI variables from linked property
bram123 Oct 11, 2026
6c3ed41
fix(metadata): fix LinkFactory phpcs issue and UriTemplateResourceMet…
bram123 Oct 11, 2026
726ddc5
Merge remote-tracking branch 'fork/link-uri-variable-schema-inference…
bram123 Oct 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog

## v5.0.3

API Platform 5.0.3 contains every change shipped in [v4.4.4](#v444) except the revert of #8600 ([#8637](https://github.com/api-platform/core/pull/8637)): 5.0 keeps documenting filterless array query parameters as both `key` and `key[]`, now guarded against `key[][]`, plus the changes below.

### Bug fixes

* [13a9c11db](https://github.com/api-platform/core/commit/13a9c11dbd7529bf792411ec002b45dca5c3c29b) fix(doctrine): avoid more deprecation from doctrine
* [37798944c](https://github.com/api-platform/core/commit/37798944c6dee10cdc6c7e4d05f008b3adb71660) fix(hal): use spl_object_id() for circular reference counters (#8657)
* [ff1bfbdde](https://github.com/api-platform/core/commit/ff1bfbddedc18fd582c855fc90da2c8660a24c68) fix(metadata): do not mutate parameters shared between operations (#8622)
* [88fab3bab](https://github.com/api-platform/core/commit/88fab3babb64e7befd44045d71ef423e97b00f66) fix(openapi): don't suffix [] on bracketed array keys (#8636)
* [ce647452b](https://github.com/api-platform/core/commit/ce647452bbc8e3ad340950f745e8c95f9fa1b75d) fix(serializer): catch MissingConstructorArgumentsException (#8659)
* [b10e80f61](https://github.com/api-platform/core/commit/b10e80f611cb0c3a9e7164a0a2156e846e456a14) fix(symfony): check HttpClientTrait before loading the test client (#8613)
* [c3eabbb9a](https://github.com/api-platform/core/commit/c3eabbb9a6bf63f7796759afd5db334b78c3d880) fix(symfony): hide the "Other API docs" label when there is only a single option (#8631)

### Dependencies

* [40711a61c](https://github.com/api-platform/core/commit/40711a61c99cee7db83256342bf6220c8925543c) chore(openapi): require json-schema ^5.0.2 (#8630)
* [5fcc64d0b](https://github.com/api-platform/core/commit/5fcc64d0b719d5cf1f725e5550615817f28b9c8d) chore: suggest ext-deepclone (#8658)

## v5.0.2

API Platform 5.0.2 contains every change shipped in [v4.4.3](#v443), plus the changes below.
Expand Down Expand Up @@ -74,6 +93,15 @@ API Platform 5.0 contains every change shipped in [v4.4.0](#v440), plus the remo
* `ApiPlatform\Symfony\Bundle\Test\ApiTestCase` and its helpers now live in the new `api-platform/test` package; the classes in the old namespace are deprecated and will be removed in 6.0 ([#7887](https://github.com/api-platform/core/pull/7887)).
* Symfony `^7.4 || ^8.0`; support for `6.4` is dropped.

## v4.4.4

### Bug fixes

* [1335871be](https://github.com/api-platform/core/commit/1335871beff7aa5d5505879732890f44b1ba2e8e) fix(hydra): handle string and null serialization groups in DocumentationNormalizer (#7890)
* [b6555c846](https://github.com/api-platform/core/commit/b6555c846a472a82099e3d7fcf6f7ec6b71aaba8) fix(laravel): ignore invalid range filter values (#8632)
* [56c0be24b](https://github.com/api-platform/core/commit/56c0be24b74366e88bdf16721b479b4cfb43877f) revert(openapi): array query params bracket notation (#8637)
* [454262ba8](https://github.com/api-platform/core/commit/454262ba8a3614d2cced01e092dcc7e14d4bb778) fix(symfony): avoid deprecated translation command probe (#8627)

## v4.4.3

### Bug fixes
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@
"webonyx/graphql-php": "^15.0"
},
"suggest": {
"ext-deepclone": "To speed up the PHP files metadata cache with symfony/var-exporter 8.1+ (install symfony/deepclone with PIE).",
"doctrine/mongodb-odm-bundle": "To support MongoDB. Only versions 4.0 and later are supported.",
"elasticsearch/elasticsearch": "To support Elasticsearch.",
"opensearch-project/opensearch-php": "To support OpenSearch (^2.5).",
Expand Down
5 changes: 3 additions & 2 deletions src/Doctrine/Orm/Extension/OrderExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace ApiPlatform\Doctrine\Orm\Extension;

use ApiPlatform\Doctrine\Orm\Util\BCHelper;
use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Exception\InvalidArgumentException;
Expand Down Expand Up @@ -69,7 +70,7 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator
$alias = QueryBuilderHelper::addJoinOnce($queryBuilder, $queryNameGenerator, $rootAlias, substr($field, 0, $pos));
$field = \sprintf('%s.%s', $alias, substr($field, $pos + 1));
}
$queryBuilder->addOrderBy($field, $order);
$queryBuilder->addOrderBy($field, BCHelper::sortDirection($order));
}

return;
Expand All @@ -82,7 +83,7 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator
}

foreach ($identifiers as $identifier) {
$queryBuilder->addOrderBy("{$rootAlias}.{$identifier}", $this->order);
$queryBuilder->addOrderBy("{$rootAlias}.{$identifier}", BCHelper::sortDirection($this->order));
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/Doctrine/Orm/Filter/OrderFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use ApiPlatform\Doctrine\Common\Filter\OrderFilterInterface;
use ApiPlatform\Doctrine\Common\Filter\OrderFilterTrait;
use ApiPlatform\Doctrine\Common\Filter\PropertyPlaceholderOpenApiParameterTrait;
use ApiPlatform\Doctrine\Orm\Util\BCHelper;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\JsonSchemaFilterInterface;
use ApiPlatform\Metadata\OpenApiParameterFilterInterface;
Expand Down Expand Up @@ -278,10 +279,10 @@ protected function filterProperty(string $property, mixed $value, QueryBuilder $
$nullRankHiddenField = \sprintf('_%s_%s_null_rank', $alias, str_replace('.', '_', $field));

$queryBuilder->addSelect(\sprintf('CASE WHEN %s.%s IS NULL THEN 0 ELSE 1 END AS HIDDEN %s', $alias, $field, $nullRankHiddenField));
$queryBuilder->addOrderBy($nullRankHiddenField, $nullsDirection);
$queryBuilder->addOrderBy($nullRankHiddenField, BCHelper::sortDirection($nullsDirection));
}

$queryBuilder->addOrderBy(\sprintf('%s.%s', $alias, $field), $direction);
$queryBuilder->addOrderBy(\sprintf('%s.%s', $alias, $field), BCHelper::sortDirection($direction));
}

/**
Expand Down
26 changes: 3 additions & 23 deletions src/Doctrine/Orm/Filter/SortFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use ApiPlatform\Doctrine\Common\Filter\OpenApiFilterTrait;
use ApiPlatform\Doctrine\Common\Filter\OrderFilterInterface;
use ApiPlatform\Doctrine\Orm\NestedPropertyHelperTrait;
use ApiPlatform\Doctrine\Orm\Util\BCHelper;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\BackwardCompatibleFilterDescriptionTrait;
use ApiPlatform\Metadata\JsonSchemaFilterInterface;
Expand Down Expand Up @@ -74,32 +75,11 @@ public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $q
if (null !== $nullsDirection) {
$nullRankHiddenField = \sprintf('_%s_%s_null_rank', $alias, str_replace('.', '_', $field));
$queryBuilder->addSelect(\sprintf('CASE WHEN %s.%s IS NULL THEN 0 ELSE 1 END AS HIDDEN %s', $alias, $field, $nullRankHiddenField));
$queryBuilder->addOrderBy($nullRankHiddenField, self::bcSortDirection($nullsDirection));
$queryBuilder->addOrderBy($nullRankHiddenField, BCHelper::sortDirection($nullsDirection));
}
}

$queryBuilder->addOrderBy(\sprintf('%s.%s', $alias, $field), self::bcSortDirection($direction));
}

/**
* @param 'ASC'|'DESC' $direction
*/
private static function bcSortDirection(string $direction): string|object
{
if (!interface_exists('Doctrine\ORM\Tools\Pagination\PaginatorInterface')) {
// doctrine/orm < 3.7
return $direction;
}

if (!enum_exists('SortDirection')) {
// PHP < 8.6 (Safety check because doctrine/orm already provides a polyfill)
return $direction;
}

return match ($direction) {
'ASC' => \SortDirection::Ascending,
'DESC' => \SortDirection::Descending,
};
$queryBuilder->addOrderBy(\sprintf('%s.%s', $alias, $field), BCHelper::sortDirection($direction));
}

/**
Expand Down
15 changes: 8 additions & 7 deletions src/Doctrine/Orm/Tests/Extension/OrderExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use ApiPlatform\Doctrine\Orm\Extension\OrderExtension;
use ApiPlatform\Doctrine\Orm\Tests\Fixtures\Entity\Dummy;
use ApiPlatform\Doctrine\Orm\Tests\Fixtures\Entity\EmbeddedDummy;
use ApiPlatform\Doctrine\Orm\Util\BCHelper;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator;
use ApiPlatform\Metadata\GetCollection;
use Doctrine\ORM\EntityManager;
Expand All @@ -37,7 +38,7 @@ public function testApplyToCollectionWithValidOrder(): void
$queryBuilderProphecy = $this->prophesize(QueryBuilder::class);

$queryBuilderProphecy->getDQLPart('orderBy')->shouldBeCalled()->willReturn([]);
$queryBuilderProphecy->addOrderBy('o.name', 'asc')->shouldBeCalled()->willReturn($queryBuilderProphecy);
$queryBuilderProphecy->addOrderBy('o.name', BCHelper::sortDirection('asc'))->shouldBeCalled()->willReturn($queryBuilderProphecy);

$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
$classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']);
Expand All @@ -58,7 +59,7 @@ public function testApplyToCollectionWithWrongOrder(): void
$queryBuilderProphecy = $this->prophesize(QueryBuilder::class);

$queryBuilderProphecy->getDQLPart('orderBy')->shouldBeCalled()->willReturn([]);
$queryBuilderProphecy->addOrderBy('o.name', 'asc')->shouldNotBeCalled();
$queryBuilderProphecy->addOrderBy('o.name', BCHelper::sortDirection('asc'))->shouldNotBeCalled();

$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
$classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']);
Expand All @@ -79,7 +80,7 @@ public function testApplyToCollectionWithOrderOverridden(): void
$queryBuilderProphecy = $this->prophesize(QueryBuilder::class);

$queryBuilderProphecy->getDQLPart('orderBy')->shouldBeCalled()->willReturn([]);
$queryBuilderProphecy->addOrderBy('o.foo', 'DESC')->shouldBeCalled()->willReturn($queryBuilderProphecy);
$queryBuilderProphecy->addOrderBy('o.foo', BCHelper::sortDirection('DESC'))->shouldBeCalled()->willReturn($queryBuilderProphecy);

$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
$classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']);
Expand All @@ -100,8 +101,8 @@ public function testApplyToCollectionWithOrderOverriddenWithNoDirection(): void
$queryBuilderProphecy = $this->prophesize(QueryBuilder::class);

$queryBuilderProphecy->getDQLPart('orderBy')->shouldBeCalled()->willReturn([]);
$queryBuilderProphecy->addOrderBy('o.foo', 'ASC')->shouldBeCalled()->willReturn($queryBuilderProphecy);
$queryBuilderProphecy->addOrderBy('o.bar', 'DESC')->shouldBeCalled()->willReturn($queryBuilderProphecy);
$queryBuilderProphecy->addOrderBy('o.foo', BCHelper::sortDirection('ASC'))->shouldBeCalled()->willReturn($queryBuilderProphecy);
$queryBuilderProphecy->addOrderBy('o.bar', BCHelper::sortDirection('DESC'))->shouldBeCalled()->willReturn($queryBuilderProphecy);

$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
$classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']);
Expand All @@ -124,7 +125,7 @@ public function testApplyToCollectionWithOrderOverriddenWithAssociation(): void
$queryBuilderProphecy->getDQLPart('orderBy')->shouldBeCalled()->willReturn([]);
$queryBuilderProphecy->getDQLPart('join')->willReturn(['o' => []])->shouldBeCalled();
$queryBuilderProphecy->innerJoin('o.author', 'author_a1', null, null)->shouldBeCalled()->willReturn($queryBuilderProphecy);
$queryBuilderProphecy->addOrderBy('author_a1.name', 'ASC')->shouldBeCalled()->willReturn($queryBuilderProphecy);
$queryBuilderProphecy->addOrderBy('author_a1.name', BCHelper::sortDirection('ASC'))->shouldBeCalled()->willReturn($queryBuilderProphecy);

$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
$classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']);
Expand All @@ -145,7 +146,7 @@ public function testApplyToCollectionWithOrderOverriddenWithEmbeddedAssociation(
$queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
$queryBuilderProphecy->getDQLPart('orderBy')->shouldBeCalled()->willReturn([]);
$queryBuilderProphecy->getRootAliases()->willReturn(['o']);
$queryBuilderProphecy->addOrderBy('o.embeddedDummy.dummyName', 'DESC')->shouldBeCalled()->willReturn($queryBuilderProphecy);
$queryBuilderProphecy->addOrderBy('o.embeddedDummy.dummyName', BCHelper::sortDirection('DESC'))->shouldBeCalled()->willReturn($queryBuilderProphecy);

$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
$classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['id']);
Expand Down
54 changes: 54 additions & 0 deletions src/Doctrine/Orm/Util/BCHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* 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\Doctrine\Orm\Util;

/**
* @internal
*/
final class BCHelper
{
private function __construct()
{
}

/**
* Maps a string sort direction to the \SortDirection enum expected by doctrine/orm >= 3.7,
* keeping the plain string for older versions.
*
* doctrine/orm 3.7 deprecates passing strings (or null) as sort directions to
* QueryBuilder::orderBy()/addOrderBy() in favor of the PHP 8.6 \SortDirection enum
* (provided on older PHP versions through symfony/polyfill-php86). Since API Platform
* still supports doctrine/orm ^2.17 || ^3.3, the enum cannot be used unconditionally.
*
* @see https://github.com/doctrine/orm/blob/3.7.x/UPGRADE.md
*/
public static function sortDirection(string $direction): string|object
{
if (!interface_exists('Doctrine\ORM\Tools\Pagination\PaginatorInterface')) {
// doctrine/orm < 3.7
return $direction;
}

if (!enum_exists('SortDirection')) {
// PHP < 8.6 (Safety check because doctrine/orm already provides a polyfill)
return $direction;
}

return match (strtoupper($direction)) {
'ASC' => \SortDirection::Ascending,
'DESC' => \SortDirection::Descending,
default => $direction,
};
}
}
12 changes: 6 additions & 6 deletions src/Hal/Serializer/ItemNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -370,19 +370,19 @@ private function isMaxDepthReached(array $attributesMetadata, string $class, str
*/
protected function isHalCircularReference(object $object, array &$context): bool
{
$objectHash = spl_object_hash($object);
$objectId = spl_object_id($object);

$circularReferenceLimit = $context[AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT] ?? $this->defaultContext[AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT];
if (isset($context[self::HAL_CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash])) {
if ($context[self::HAL_CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash] >= $circularReferenceLimit) {
unset($context[self::HAL_CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash]);
if (isset($context[self::HAL_CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectId])) {
if ($context[self::HAL_CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectId] >= $circularReferenceLimit) {
unset($context[self::HAL_CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectId]);

return true;
}

++$context[self::HAL_CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash];
++$context[self::HAL_CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectId];
} else {
$context[self::HAL_CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash] = 1;
$context[self::HAL_CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectId] = 1;
}

return false;
Expand Down
12 changes: 10 additions & 2 deletions src/Hydra/Serializer/DocumentationNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,16 @@ private function getClass(string $resourceClass, ApiResource $resourceMetadata,
*/
private function getPropertyMetadataFactoryContext(ApiResource $resourceMetadata): array
{
$normalizationGroups = $resourceMetadata->getNormalizationContext()[AbstractNormalizer::GROUPS] ?? null;
$denormalizationGroups = $resourceMetadata->getDenormalizationContext()[AbstractNormalizer::GROUPS] ?? null;
$normalizationGroups = ($resourceMetadata->getNormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null;
$denormalizationGroups = ($resourceMetadata->getDenormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null;

if (\is_string($normalizationGroups)) {
$normalizationGroups = [$normalizationGroups];
}
if (\is_string($denormalizationGroups)) {
$denormalizationGroups = [$denormalizationGroups];
}

$propertyContext = [
'normalization_groups' => $normalizationGroups,
'denormalization_groups' => $denormalizationGroups,
Expand Down
50 changes: 50 additions & 0 deletions src/Hydra/Tests/Serializer/DocumentationNormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1162,4 +1162,54 @@

$this->assertEquals($expected, $documentationNormalizer->normalize($documentation, null, [ContextBuilder::HYDRA_CONTEXT_HAS_PREFIX => false]));
}

public function testNormalizeWithStringGroups(): void
{
$title = 'Test Api';
$desc = 'test';
$version = '0.0.0';
$documentation = new Documentation(new ResourceNameCollection(['dummy' => 'dummy']), $title, $desc, $version);

$propertyNameCollectionFactory = $this->createMock(PropertyNameCollectionFactoryInterface::class);
$propertyNameCollectionFactory->expects($this->once())->method('create')->with('dummy', $this->isArray())->willReturn(new PropertyNameCollection(['name']));

$propertyMetadataFactory = $this->createMock(PropertyMetadataFactoryInterface::class);
$propertyMetadataFactory->expects($this->once())->method('create')->with('dummy', 'name', $this->isArray())->willReturn(
(new ApiProperty())->withNativeType(Type::string())->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)
);

$resourceMetadataFactory = $this->createMock(ResourceMetadataCollectionFactoryInterface::class);
$resourceMetadataFactory->expects($this->once())->method('create')->with('dummy')->willReturn(new ResourceMetadataCollection('dummy', [
(new ApiResource())
->withShortName('dummy')
->withOperations(new Operations([
'get' => (new Get())->withShortName('dummy'),
]))
->withNormalizationContext(['groups' => 'read'])
->withDenormalizationContext(['groups' => 'write']),
]));

$resourceClassResolver = $this->createMock(ResourceClassResolverInterface::class);
$resourceClassResolver->method('isResourceClass')->with($this->isString())->willReturn(false);

Check failure on line 1193 in src/Hydra/Tests/Serializer/DocumentationNormalizerTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (PHP 8.5)

Call to an undefined method PHPUnit\Framework\MockObject\InvocationStubber::with().

$urlGenerator = $this->createMock(UrlGeneratorInterface::class);
$urlGenerator->method('generate')->willReturnMap([
['api_entrypoint', '/'],
['api_doc', ['_format' => 'jsonld'], '/doc'],
['api_doc', ['_format' => 'jsonld'], 0, '/doc'],
]);

$documentationNormalizer = new DocumentationNormalizer(
$resourceMetadataFactory,
$propertyNameCollectionFactory,
$propertyMetadataFactory,
$resourceClassResolver,
$urlGenerator
);

$doc = $documentationNormalizer->normalize($documentation);

$this->assertSame('#dummy', $doc['hydra:supportedClass'][0]['@id']);
$this->assertNotEmpty($doc['hydra:supportedClass'][0]['hydra:supportedProperty']);
}
}
Loading
Loading