Skip to content

Commit 5de2f08

Browse files
committed
add flag metadata + few fixes + headers/status
1 parent ea5077d commit 5de2f08

23 files changed

+300
-116
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@
110110
"symfony/deprecation-contracts": "^3.1",
111111
"symfony/http-foundation": "^6.4 || ^7.0",
112112
"symfony/http-kernel": "^6.4 || ^7.0",
113-
"symfony/json-streamer": "^7.3",
114113
"symfony/property-access": "^6.4 || ^7.0",
115114
"symfony/property-info": "^6.4 || ^7.1",
116115
"symfony/serializer": "^6.4 || ^7.0",
@@ -173,9 +172,10 @@
173172
"symfony/expression-language": "^6.4 || ^7.0",
174173
"symfony/finder": "^6.4 || ^7.0",
175174
"symfony/form": "^6.4 || ^7.0",
176-
"symfony/framework-bundle": "^6.4 || ^7.0",
175+
"symfony/framework-bundle": "7.4.x-dev",
177176
"symfony/http-client": "^6.4 || ^7.0",
178177
"symfony/intl": "^6.4 || ^7.0",
178+
"symfony/json-streamer": "7.4.x-dev",
179179
"symfony/maker-bundle": "^1.24",
180180
"symfony/mercure-bundle": "*",
181181
"symfony/messenger": "^6.4 || ^7.0",

src/Hydra/State/JsonStreamerProcessor.php

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,31 @@
2626
use ApiPlatform\State\Pagination\PaginatorInterface;
2727
use ApiPlatform\State\Pagination\PartialPaginatorInterface;
2828
use ApiPlatform\State\ProcessorInterface;
29+
use ApiPlatform\State\Util\HttpResponseHeadersTrait;
30+
use ApiPlatform\State\Util\HttpResponseStatusTrait;
2931
use Symfony\Component\HttpFoundation\Response;
3032
use Symfony\Component\HttpFoundation\StreamedResponse;
3133
use Symfony\Component\JsonStreamer\StreamWriterInterface;
3234
use Symfony\Component\TypeInfo\Type;
3335

36+
/**
37+
* @implements ProcessorInterface<mixed,mixed>
38+
*/
3439
final class JsonStreamerProcessor implements ProcessorInterface
3540
{
41+
use HttpResponseHeadersTrait;
42+
use HttpResponseStatusTrait;
43+
44+
/**
45+
* @param ProcessorInterface<mixed,mixed> $processor
46+
* @param StreamWriterInterface<array<string,mixed>> $jsonStreamer
47+
*/
3648
public function __construct(
3749
private readonly ProcessorInterface $processor,
3850
private readonly StreamWriterInterface $jsonStreamer,
3951
private readonly string $pageParameterName = 'page',
4052
private readonly string $enabledParameterName = 'pagination',
41-
private readonly int $urlGenerationStrategy = UrlGeneratorInterface::ABS_PATH
53+
private readonly int $urlGenerationStrategy = UrlGeneratorInterface::ABS_PATH,
4254
) {
4355
}
4456

@@ -67,6 +79,7 @@ private function getSearch(Operation $operation, string $requestUri): IriTemplat
6779
}
6880

6981
$parts = parse_url($requestUri);
82+
7083
return new IriTemplate(
7184
variableRepresentation: 'BasicRepresentation',
7285
mapping: $mapping,
@@ -120,7 +133,12 @@ private function getView(mixed $object, string $requestUri, Operation $operation
120133

121134
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = [])
122135
{
123-
if ($context['request']->query->has('skip_json_stream')) {
136+
if (!$operation->getJsonStream() || !($request = $context['request'] ?? null)) {
137+
return $this->processor->process($data, $operation, $uriVariables, $context);
138+
}
139+
140+
// TODO: remove this before merging
141+
if ($request->query->has('skip_json_stream')) {
124142
return $this->processor->process($data, $operation, $uriVariables, $context);
125143
}
126144

@@ -129,7 +147,7 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
129147
}
130148

131149
if ($operation instanceof CollectionOperationInterface) {
132-
$requestUri = $context['request']->getRequestUri() ?? '';
150+
$requestUri = $request->getRequestUri() ?? '';
133151
$collection = new Collection();
134152
$collection->member = $data;
135153
$collection->view = $this->getView($data, $requestUri, $operation);
@@ -146,17 +164,25 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
146164
$collection->totalItems = \count($data);
147165
}
148166

149-
$response = new StreamedResponse($this->jsonStreamer->write($collection, Type::generic(Type::object($collection::class), Type::object($operation->getClass())), [
150-
'data' => $data,
151-
'operation' => $operation,
152-
]));
167+
$data = $this->jsonStreamer->write(
168+
$collection,
169+
Type::generic(Type::object($collection::class), Type::object($operation->getClass())),
170+
['data' => $data, 'operation' => $operation],
171+
);
153172
} else {
154-
$response = new StreamedResponse($this->jsonStreamer->write($data, Type::object($operation->getClass()), [
173+
$data = $this->jsonStreamer->write($data, Type::object($operation->getClass()), [
155174
'data' => $data,
156175
'operation' => $operation,
157-
]));
176+
]);
158177
}
159178

179+
/** @var Iterable<string> $data */
180+
$response = new StreamedResponse(
181+
$data,
182+
$this->getStatus($request, $operation, $context),
183+
$this->getHeaders($request, $operation, $context)
184+
);
185+
160186
return $this->processor->process($response, $operation, $uriVariables, $context);
161187
}
162188
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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\JsonLd\JsonStreamer\ValueTransformer;
15+
16+
use ApiPlatform\Metadata\UrlGeneratorInterface;
17+
use Symfony\Component\JsonStreamer\ValueTransformer\ValueTransformerInterface;
18+
use Symfony\Component\TypeInfo\Type;
19+
20+
final class ContextValueTransformer implements ValueTransformerInterface
21+
{
22+
public function __construct(
23+
private readonly UrlGeneratorInterface $urlGenerator,
24+
) {
25+
}
26+
27+
public function transform(mixed $value, array $options = []): mixed
28+
{
29+
return $this->urlGenerator->generate('api_jsonld_context', ['shortName' => $options['operation']->getShortName()], $options['operation']->getUrlGenerationStrategy());
30+
}
31+
32+
public static function getStreamValueType(): Type
33+
{
34+
return Type::string();
35+
}
36+
}

src/JsonLd/JsonStreamer/IriValueTransformer.php renamed to src/JsonLd/JsonStreamer/ValueTransformer/IriValueTransformer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace ApiPlatform\JsonLd\JsonStreamer;
5+
namespace ApiPlatform\JsonLd\JsonStreamer\ValueTransformer;
66

77
use ApiPlatform\Hydra\Collection;
88
use ApiPlatform\Metadata\CollectionOperationInterface;

src/JsonLd/JsonStreamer/WritePropertyMetadataLoader.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use ApiPlatform\Hydra\IriTemplate;
1717
use ApiPlatform\Hydra\Collection;
1818
use ApiPlatform\Metadata\ResourceClassResolverInterface;
19-
use ApiPlatform\Metadata\UrlGeneratorInterface;
2019
use ApiPlatform\Metadata\Util\TypeHelper;
2120
use Symfony\Component\JsonStreamer\Mapping\PropertyMetadata;
2221
use Symfony\Component\JsonStreamer\Mapping\PropertyMetadataLoaderInterface;
@@ -27,7 +26,6 @@ final class WritePropertyMetadataLoader implements PropertyMetadataLoaderInterfa
2726
public function __construct(
2827
private readonly PropertyMetadataLoaderInterface $loader,
2928
private readonly ResourceClassResolverInterface $resourceClassResolver,
30-
private readonly UrlGeneratorInterface $urlGenerator,
3129
) {
3230
}
3331

@@ -63,7 +61,7 @@ public function load(string $className, array $options = [], array $context = []
6361
$properties['@context'] = new PropertyMetadata(
6462
'id', // virual property
6563
Type::string(), // virtual property
66-
staticValue: $this->urlGenerator->generate('api_jsonld_context', ['shortName' => $options['operation']->getShortName()], $options['operation']->getUrlGenerationStrategy()),
64+
['api_platform.jsonld.json_streamer.write.value_transformer.context'],
6765
);
6866
}
6967

src/Metadata/ApiResource.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,7 @@ public function __construct(
965965
array|Parameters|null $parameters = null,
966966
protected ?bool $strictQueryParameterValidation = null,
967967
protected ?bool $hideHydraOperation = null,
968+
?bool $jsonStream = null,
968969
protected array $extraProperties = [],
969970
) {
970971
parent::__construct(
@@ -1011,6 +1012,7 @@ class: $class,
10111012
middleware: $middleware,
10121013
strictQueryParameterValidation: $strictQueryParameterValidation,
10131014
hideHydraOperation: $hideHydraOperation,
1015+
jsonStream: $jsonStream,
10141016
extraProperties: $extraProperties
10151017
);
10161018

src/Metadata/Delete.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public function __construct(
100100
array|string|null $middleware = null,
101101
?bool $strictQueryParameterValidation = null,
102102
protected ?bool $hideHydraOperation = null,
103+
?bool $jsonStream = null,
103104
array $extraProperties = [],
104105
) {
105106
parent::__construct(
@@ -177,6 +178,7 @@ class: $class,
177178
rules: $rules,
178179
policy: $policy,
179180
middleware: $middleware,
181+
jsonStream: $jsonStream,
180182
extraProperties: $extraProperties,
181183
collectDenormalizationErrors: $collectDenormalizationErrors,
182184
parameters: $parameters,

src/Metadata/Error.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public function __construct(
9595
$processor = null,
9696
?OptionsInterface $stateOptions = null,
9797
?bool $hideHydraOperation = null,
98+
?bool $jsonStream = null,
9899
array $extraProperties = [],
99100
) {
100101
parent::__construct(
@@ -171,6 +172,7 @@ class: $class,
171172
processor: $processor,
172173
stateOptions: $stateOptions,
173174
hideHydraOperation: $hideHydraOperation,
175+
jsonStream: $jsonStream,
174176
extraProperties: $extraProperties,
175177
);
176178
}

src/Metadata/ErrorResource.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public function __construct(
8484
$provider = null,
8585
$processor = null,
8686
?OptionsInterface $stateOptions = null,
87+
?bool $jsonStream = null,
8788
array $extraProperties = [],
8889
) {
8990
parent::__construct(
@@ -151,6 +152,7 @@ class: $class,
151152
provider: $provider,
152153
processor: $processor,
153154
stateOptions: $stateOptions,
155+
jsonStream: $jsonStream,
154156
extraProperties: $extraProperties
155157
);
156158
}

src/Metadata/Get.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public function __construct(
100100
array|string|null $middleware = null,
101101
?bool $strictQueryParameterValidation = null,
102102
protected ?bool $hideHydraOperation = null,
103+
?bool $jsonStream = null,
103104
array $extraProperties = [],
104105
) {
105106
parent::__construct(
@@ -181,6 +182,7 @@ class: $class,
181182
middleware: $middleware,
182183
strictQueryParameterValidation: $strictQueryParameterValidation,
183184
hideHydraOperation: $hideHydraOperation,
185+
jsonStream: $jsonStream,
184186
extraProperties: $extraProperties,
185187
);
186188
}

0 commit comments

Comments
 (0)