Skip to content

Commit 6abd0fe

Browse files
soyukahelyakinArnoudThibautdavy-beauzilKorbeil
authored
Merge 3.0 into main (api-platform#5121)
* fix: update yaml extractor test file coding standard (api-platform#5068) * fix(graphql): add clearer error message when TwigBundle is disabled but graphQL clients are enabled (api-platform#5064) * fix(metadata): add class key in payload argument resolver (api-platform#5067) * fix: add class key in payload argument resolver * add null if everything else goes wrong * fix: upgrade command remove ApiSubresource attribute (api-platform#5049) Fixes api-platform#5038 * fix(doctrine): use abitrary index instead of value (api-platform#5079) * fix: uri template should respect rfc 6570 (api-platform#5080) * fix: remove @internal annotation for Operations (api-platform#5089) See api-platform#5084 * fix(metadata): define a name on a single operation (api-platform#5090) fixes api-platform#5082 * fix(metadata): deprecate when user decorates in legacy mode (api-platform#5091) fixes api-platform#5078 * fix(graphql): use right nested operation (api-platform#5102) * Revert "fix(graphql): use right nested operation (api-platform#5102)" (api-platform#5111) This reverts commit 44337dd. * fix(graphql): always allow to query nested resources (api-platform#5112) * fix(graphql): always allow to query nested resources * review Co-authored-by: Alan Poulain <[email protected]> * chore: php-cs-fixer update * fix: only alias if exists for opcache preload Fixes api-platform/api-platform#2284 (api-platform#5110) Co-authored-by: Liviu Mirea <[email protected]> * chore: php-cs-fixer update (api-platform#5118) * chore: php-cs-fixer update * chore: php-cs-fixer update * fix(metadata): upgrade script keep operation name (api-platform#5109) origin: api-platform#5105 Co-authored-by: WilliamPeralta <[email protected]> * chore: v2.7.3 changelog * chore: v3.0.3 changelog Co-authored-by: helyakin <[email protected]> Co-authored-by: ArnoudThibaut <[email protected]> Co-authored-by: davy-beauzil <[email protected]> Co-authored-by: Baptiste Leduc <[email protected]> Co-authored-by: Xavier Laviron <[email protected]> Co-authored-by: Alan Poulain <[email protected]> Co-authored-by: Liviu Cristian Mirea-Ghiban <[email protected]> Co-authored-by: Liviu Mirea <[email protected]> Co-authored-by: WilliamPeralta <[email protected]>
1 parent ac70771 commit 6abd0fe

File tree

93 files changed

+1128
-462
lines changed

Some content is hidden

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

93 files changed

+1128
-462
lines changed

CHANGELOG.md

+32
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# Changelog
22

3+
## v3.0.3
4+
5+
### Bug fixes
6+
7+
* [176fff2cb](https://github.com/api-platform/core/commit/176fff2cb15efa01b6c898d0442a4f540d4ddeaa) fix(metadata): upgrade script keep operation name (#5109)
8+
* [1b64ebf6a](https://github.com/api-platform/core/commit/1b64ebf6a438222ae091ec3690063d0fb1b61977) fix: upgrade command remove ApiSubresource attribute (#5049)
9+
* [27fcdc6b2](https://github.com/api-platform/core/commit/27fcdc6b270d1699e76c37ccda690b8a5ed8b4c9) fix(metadata): deprecate when user decorates in legacy mode (#5091)
10+
* [310363d56](https://github.com/api-platform/core/commit/310363d56129c94cf4d51977f85486729e582fbc) fix: remove @internal annotation for Operations (#5089)
11+
* [41bbad94e](https://github.com/api-platform/core/commit/41bbad94e93df49eb4ade0fe1307b20d9cd07102) fix: update yaml extractor test file coding standard (#5068)
12+
* [44337ddb3](https://github.com/api-platform/core/commit/44337ddb3908d7b05ed75b75325b7941581f575b) fix(graphql): use right nested operation (#5102)
13+
* [541b738e9](https://github.com/api-platform/core/commit/541b738e942156b711665952b50fbd4f060fcdea) fix(graphql): add clearer error message when TwigBundle is disabled but graphQL clients are enabled (#5064)
14+
* [59826bbe9](https://github.com/api-platform/core/commit/59826bbe9e246cf839bdc0c4d0d470f54e27b453) fix: only alias if exists for opcache preload
15+
* [7044c5a1b](https://github.com/api-platform/core/commit/7044c5a1b2895e72f0579d1e788740606f94dece) fix(doctrine): use abitrary index instead of value (#5079)
16+
* [8250d41a3](https://github.com/api-platform/core/commit/8250d41a38913a17364d617875bb5a90f434ec48) fix(metadata): define a name on a single operation (#5090)
17+
* [9c19fa171](https://github.com/api-platform/core/commit/9c19fa17110aac7dd39bff827091c00b42a80d4f) fix(metadata): add class key in payload argument resolver (#5067)
18+
* [a4cd12b2a](https://github.com/api-platform/core/commit/a4cd12b2a73bc0f726c5724de790f885884e6113) fix: uri template should respect rfc 6570 (#5080)
19+
* [bbeaf7082](https://github.com/api-platform/core/commit/bbeaf7082bba4a019206c3862425cf849d55addd) fix(graphql): always allow to query nested resources (#5112)
20+
* [c1cb3cd2f](https://github.com/api-platform/core/commit/c1cb3cd2ff32c8b1ee694b0989efeb133fbd8438) Revert "fix(graphql): use right nested operation (#5102)" (#5111)
21+
322
## 3.0.2
423

524
* Metadata: generate skolem IRI by default, use `genId: false` to disable **BC**
@@ -54,6 +73,19 @@ Breaking changes:
5473
* Serializer: `skip_null_values` now defaults to `true`
5574
* Metadata: `Patch` is added to the automatic CRUD
5675

76+
## v2.7.3
77+
78+
### Bug fixes
79+
80+
* [176fff2cb](https://github.com/api-platform/core/commit/176fff2cb15efa01b6c898d0442a4f540d4ddeaa) fix(metadata): upgrade script keep operation name (#5109)
81+
* [1b64ebf6a](https://github.com/api-platform/core/commit/1b64ebf6a438222ae091ec3690063d0fb1b61977) fix: upgrade command remove ApiSubresource attribute (#5049)
82+
* [27fcdc6b2](https://github.com/api-platform/core/commit/27fcdc6b270d1699e76c37ccda690b8a5ed8b4c9) fix(metadata): deprecate when user decorates in legacy mode (#5091)
83+
* [310363d56](https://github.com/api-platform/core/commit/310363d56129c94cf4d51977f85486729e582fbc) fix: remove @internal annotation for Operations (#5089)
84+
* [41bbad94e](https://github.com/api-platform/core/commit/41bbad94e93df49eb4ade0fe1307b20d9cd07102) fix: update yaml extractor test file coding standard (#5068)
85+
* [59826bbe9](https://github.com/api-platform/core/commit/59826bbe9e246cf839bdc0c4d0d470f54e27b453) fix: only alias if exists for opcache preload
86+
* [8250d41a3](https://github.com/api-platform/core/commit/8250d41a38913a17364d617875bb5a90f434ec48) fix(metadata): define a name on a single operation (#5090)
87+
* [9c19fa171](https://github.com/api-platform/core/commit/9c19fa17110aac7dd39bff827091c00b42a80d4f) fix(metadata): add class key in payload argument resolver (#5067)
88+
5789
## 2.7.2
5890

5991
* Metadata: no skolem IRI by default

features/graphql/collection.feature

+46
Original file line numberDiff line numberDiff line change
@@ -910,3 +910,49 @@ Feature: GraphQL collection support
910910
Then the response status code should be 200
911911
And the response should be in JSON
912912
And the JSON node "data.fooDummies.collection" should have 1 element
913+
914+
@createSchema
915+
Scenario: Retrieve paginated collections using mixed pagination
916+
Given there are 5 fooDummy objects with fake names
917+
When I send the following GraphQL request:
918+
"""
919+
{
920+
fooDummies(page: 1) {
921+
collection {
922+
id
923+
name
924+
soManies(first: 2) {
925+
edges {
926+
node {
927+
content
928+
}
929+
cursor
930+
}
931+
pageInfo {
932+
startCursor
933+
endCursor
934+
hasNextPage
935+
hasPreviousPage
936+
}
937+
}
938+
}
939+
paginationInfo {
940+
itemsPerPage
941+
lastPage
942+
totalCount
943+
}
944+
}
945+
}
946+
"""
947+
Then the response status code should be 200
948+
And the response should be in JSON
949+
And the JSON node "data.fooDummies.collection" should have 3 elements
950+
And the JSON node "data.fooDummies.collection[2].id" should exist
951+
And the JSON node "data.fooDummies.collection[2].name" should exist
952+
And the JSON node "data.fooDummies.collection[2].soManies" should exist
953+
And the JSON node "data.fooDummies.collection[2].soManies.edges" should have 2 elements
954+
And the JSON node "data.fooDummies.collection[2].soManies.edges[1].node.content" should be equal to "So many 1"
955+
And the JSON node "data.fooDummies.collection[2].soManies.pageInfo.startCursor" should be equal to "MA=="
956+
And the JSON node "data.fooDummies.paginationInfo.itemsPerPage" should be equal to the number 3
957+
And the JSON node "data.fooDummies.paginationInfo.lastPage" should be equal to the number 2
958+
And the JSON node "data.fooDummies.paginationInfo.totalCount" should be equal to the number 5

features/main/default_order.feature

+31-5
Original file line numberDiff line numberDiff line change
@@ -79,35 +79,61 @@ Feature: Default order
7979
"@type": "FooDummy",
8080
"id": 5,
8181
"name": "Balbo",
82-
"dummy": "/dummies/5"
82+
"dummy": "/dummies/5",
83+
"soManies": [
84+
"/so_manies/13",
85+
"/so_manies/14",
86+
"/so_manies/15"
87+
]
88+
8389
},
8490
{
8591
"@id": "/foo_dummies/3",
8692
"@type": "FooDummy",
8793
"id": 3,
8894
"name": "Sthenelus",
89-
"dummy": "/dummies/3"
95+
"dummy": "/dummies/3",
96+
"soManies": [
97+
"/so_manies/7",
98+
"/so_manies/8",
99+
"/so_manies/9"
100+
]
90101
},
91102
{
92103
"@id": "/foo_dummies/2",
93104
"@type": "FooDummy",
94105
"id": 2,
95106
"name": "Ephesian",
96-
"dummy": "/dummies/2"
107+
"dummy": "/dummies/2",
108+
"soManies": [
109+
"/so_manies/4",
110+
"/so_manies/5",
111+
"/so_manies/6"
112+
]
97113
},
98114
{
99115
"@id": "/foo_dummies/1",
100116
"@type": "FooDummy",
101117
"id": 1,
102118
"name": "Hawsepipe",
103-
"dummy": "/dummies/1"
119+
"dummy": "/dummies/1",
120+
"soManies": [
121+
"/so_manies/1",
122+
"/so_manies/2",
123+
"/so_manies/3"
124+
]
104125
},
105126
{
106127
"@id": "/foo_dummies/4",
107128
"@type": "FooDummy",
108129
"id": 4,
109130
"name": "Separativeness",
110-
"dummy": "/dummies/4"
131+
"dummy": "/dummies/4",
132+
"soManies": [
133+
"/so_manies/10",
134+
"/so_manies/11",
135+
"/so_manies/12"
136+
]
111137
}
112138
],
113139
"hydra:totalItems": 5,

generate-changelog.sh

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
# usage: generate-changelog.sh previous_tag next_tag
3+
# example: generate-changelog.sh v2.7.2 v2.7.3 > CHANGELOG.new.md
4+
log=$(git log "$1..HEAD" --pretty='format:* [%h](https://github.com/api-platform/core/commit/%H) %s' --no-merges)
5+
6+
diff=$(
7+
printf "# Changelog\n\n"
8+
printf "## %s\n\n" "$2"
9+
10+
if [[ 0 != $(echo "$log" | grep fix | grep -v chore | wc -l) ]];
11+
then
12+
printf "### Bug fixes\n\n"
13+
printf "$log" | grep fix | grep -v chore | sort
14+
printf "\n\n"
15+
fi
16+
17+
if [[ 0 != $(echo "$log" | grep feat | grep -v chore | wc -l) ]];
18+
then
19+
printf "### Features\n\n"
20+
printf "$log" | grep feat | grep -v chore | sort
21+
fi
22+
)
23+
24+
changelog=$(tail -n+2 CHANGELOG.md)
25+
printf "%s\n%s" "$diff" "$changelog"

src/Doctrine/Odm/Extension/OrderExtension.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
use Doctrine\ODM\MongoDB\Aggregation\Builder;
2020
use Doctrine\ODM\MongoDB\Aggregation\Stage\Sort;
2121
use Doctrine\Persistence\ManagerRegistry;
22-
use OutOfRangeException;
2322

2423
/**
2524
* Applies selected ordering while querying resource collection.
@@ -100,7 +99,7 @@ private function hasSortStage(Builder $aggregationBuilder): bool
10099
// If at least one stage is sort, then it has sorting
101100
return true;
102101
}
103-
} catch (OutOfRangeException) {
102+
} catch (\OutOfRangeException $outOfRangeException) {
104103
// There is no more stages on the aggregation builder
105104
$shouldStop = true;
106105
}

src/Doctrine/Orm/Filter/SearchFilter.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ protected function addWhereByStrategy(string $strategy, QueryBuilder $queryBuild
179179
$parameters = [];
180180
foreach ($values as $key => $value) {
181181
$keyValueParameter = sprintf('%s_%s', $valueParameter, $key);
182-
$parameters[$caseSensitive ? $value : strtolower($value)] = $keyValueParameter;
182+
$parameters[] = [$caseSensitive ? $value : strtolower($value), $keyValueParameter];
183183

184184
$ors[] = match ($strategy) {
185185
self::STRATEGY_PARTIAL => $queryBuilder->expr()->like(
@@ -209,7 +209,9 @@ protected function addWhereByStrategy(string $strategy, QueryBuilder $queryBuild
209209
}
210210

211211
$queryBuilder->andWhere($queryBuilder->expr()->orX(...$ors));
212-
array_walk($parameters, $queryBuilder->setParameter(...));
212+
foreach ($parameters as $parameter) {
213+
$queryBuilder->setParameter($parameter[1], $parameter[0]);
214+
}
213215
}
214216

215217
/**

src/GraphQl/Action/EntrypointAction.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ final class EntrypointAction
3434
{
3535
private int $debug;
3636

37-
public function __construct(private readonly SchemaBuilderInterface $schemaBuilder, private readonly ExecutorInterface $executor, private readonly GraphiQlAction $graphiQlAction, private readonly GraphQlPlaygroundAction $graphQlPlaygroundAction, private readonly NormalizerInterface $normalizer, private readonly ErrorHandlerInterface $errorHandler, bool $debug = false, private readonly bool $graphiqlEnabled = false, private readonly bool $graphQlPlaygroundEnabled = false, private readonly ?string $defaultIde = null)
37+
public function __construct(private readonly SchemaBuilderInterface $schemaBuilder, private readonly ExecutorInterface $executor, private readonly ?GraphiQlAction $graphiQlAction, private readonly ?GraphQlPlaygroundAction $graphQlPlaygroundAction, private readonly NormalizerInterface $normalizer, private readonly ErrorHandlerInterface $errorHandler, bool $debug = false, private readonly bool $graphiqlEnabled = false, private readonly bool $graphQlPlaygroundEnabled = false, private readonly ?string $defaultIde = null)
3838
{
3939
$this->debug = $debug ? DebugFlag::INCLUDE_DEBUG_MESSAGE | DebugFlag::INCLUDE_TRACE : DebugFlag::NONE;
4040
}
@@ -43,11 +43,11 @@ public function __invoke(Request $request): Response
4343
{
4444
try {
4545
if ($request->isMethod('GET') && 'html' === $request->getRequestFormat()) {
46-
if ('graphiql' === $this->defaultIde && $this->graphiqlEnabled) {
46+
if ('graphiql' === $this->defaultIde && $this->graphiqlEnabled && $this->graphiQlAction) {
4747
return ($this->graphiQlAction)($request);
4848
}
4949

50-
if ('graphql-playground' === $this->defaultIde && $this->graphQlPlaygroundEnabled) {
50+
if ('graphql-playground' === $this->defaultIde && $this->graphQlPlaygroundEnabled && $this->graphQlPlaygroundAction) {
5151
return ($this->graphQlPlaygroundAction)($request);
5252
}
5353
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\GraphQl\Metadata\Factory;
15+
16+
use ApiPlatform\Metadata\ApiResource;
17+
use ApiPlatform\Metadata\Resource\Factory\OperationDefaultsTrait;
18+
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
19+
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
20+
use Psr\Log\LoggerInterface;
21+
use Psr\Log\NullLogger;
22+
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
23+
24+
final class GraphQlNestedOperationResourceMetadataFactory implements ResourceMetadataCollectionFactoryInterface
25+
{
26+
use OperationDefaultsTrait;
27+
28+
public function __construct(array $defaults, private readonly ?ResourceMetadataCollectionFactoryInterface $decorated = null, ?LoggerInterface $logger = null)
29+
{
30+
$this->defaults = $defaults;
31+
$this->camelCaseToSnakeCaseNameConverter = new CamelCaseToSnakeCaseNameConverter();
32+
$this->logger = $logger ?? new NullLogger();
33+
}
34+
35+
public function create(string $resourceClass): ResourceMetadataCollection
36+
{
37+
$resourceMetadataCollection = new ResourceMetadataCollection($resourceClass);
38+
39+
if ($this->decorated) {
40+
$resourceMetadataCollection = $this->decorated->create($resourceClass);
41+
}
42+
43+
if (0 < \count($resourceMetadataCollection)) {
44+
return $resourceMetadataCollection;
45+
}
46+
47+
$shortName = (false !== $pos = strrpos($resourceClass, '\\')) ? substr($resourceClass, $pos + 1) : $resourceClass;
48+
49+
$apiResource = new ApiResource(
50+
class: $resourceClass,
51+
shortName: $shortName
52+
);
53+
54+
if (class_exists($resourceClass)) {
55+
$refl = new \ReflectionClass($resourceClass);
56+
$attribute = $refl->getAttributes(ApiResource::class)[0] ?? null;
57+
$attributeInstance = $attribute?->newInstance();
58+
if ($filters = $attributeInstance?->getFilters()) {
59+
$apiResource = $apiResource->withFilters($filters);
60+
}
61+
}
62+
63+
$resourceMetadataCollection[0] = $this->addDefaultGraphQlOperations($apiResource);
64+
65+
return $resourceMetadataCollection;
66+
}
67+
}

0 commit comments

Comments
 (0)