Skip to content

Commit b8b6b1f

Browse files
committed
listeners
1 parent 7fb9b4d commit b8b6b1f

File tree

9 files changed

+254
-44
lines changed

9 files changed

+254
-44
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
"symfony/property-info": "^6.4 || ^7.1",
117117
"symfony/serializer": "^6.4 || ^7.0",
118118
"symfony/translation-contracts": "^3.3",
119-
"symfony/type-info": "7.4.x-dev",
119+
"symfony/type-info": "^7.3 || 7.4.x-dev",
120120
"symfony/validator": "^6.4 || ^7.1",
121121
"symfony/web-link": "^6.4 || ^7.1",
122122
"willdurand/negotiation": "^3.1"

src/Hydra/State/JsonStreamerProcessor.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ final class JsonStreamerProcessor implements ProcessorInterface
4545
use SearchHelperTrait;
4646

4747
/**
48-
* @param ProcessorInterface<mixed,mixed> $processor
48+
* @param ProcessorInterface<mixed,mixed>|null $processor
4949
* @param StreamWriterInterface<array<string,mixed>> $jsonStreamer
5050
*/
5151
public function __construct(
52-
private readonly ProcessorInterface $processor,
52+
private readonly ?ProcessorInterface $processor,
5353
private readonly StreamWriterInterface $jsonStreamer,
5454
?IriConverterInterface $iriConverter = null,
5555
?ResourceClassResolverInterface $resourceClassResolver = null,
@@ -73,7 +73,7 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
7373
|| !$operation->getJsonStream()
7474
|| 'jsonld' !== $request->getRequestFormat()
7575
) {
76-
return $this->processor->process($data, $operation, $uriVariables, $context);
76+
return $this->processor?->process($data, $operation, $uriVariables, $context);
7777
}
7878

7979
if ($operation instanceof CollectionOperationInterface) {
@@ -115,6 +115,6 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
115115
$this->getHeaders($request, $operation, $context)
116116
);
117117

118-
return $this->processor->process($response, $operation, $uriVariables, $context);
118+
return $this->processor ? $this->processor->process($response, $operation, $uriVariables, $context) : $response;
119119
}
120120
}

src/Serializer/State/JsonStreamerProcessor.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ final class JsonStreamerProcessor implements ProcessorInterface
3737
use HttpResponseStatusTrait;
3838

3939
/**
40-
* @param ProcessorInterface<mixed,mixed> $processor
40+
* @param ProcessorInterface<mixed,mixed>|null $processor
4141
* @param StreamWriterInterface<array<string,mixed>> $jsonStreamer
4242
*/
4343
public function __construct(
44-
private readonly ProcessorInterface $processor,
44+
private readonly ?ProcessorInterface $processor,
4545
private readonly StreamWriterInterface $jsonStreamer,
4646
?IriConverterInterface $iriConverter = null,
4747
?ResourceClassResolverInterface $resourceClassResolver = null,
@@ -62,7 +62,7 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
6262
|| !$operation->getJsonStream()
6363
|| 'json' !== $request->getRequestFormat()
6464
) {
65-
return $this->processor->process($data, $operation, $uriVariables, $context);
65+
return $this->processor?->process($data, $operation, $uriVariables, $context);
6666
}
6767

6868
if ($operation instanceof CollectionOperationInterface) {
@@ -86,6 +86,6 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
8686
$this->getHeaders($request, $operation, $context)
8787
);
8888

89-
return $this->processor->process($response, $operation, $uriVariables, $context);
89+
return $this->processor ? $this->processor->process($response, $operation, $uriVariables, $context) : $response;
9090
}
9191
}

src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -993,11 +993,20 @@ private function registerJsonStreamerConfiguration(ContainerBuilder $container,
993993
$container->setParameter('.json_streamer.stream_writers_dir.jsonld', '%kernel.cache_dir%/json_streamer/stream_writer/jsonld');
994994
$container->setParameter('.json_streamer.stream_readers_dir.jsonld', '%kernel.cache_dir%/json_streamer/stream_reader/jsonld');
995995
$container->setParameter('.json_streamer.lazy_ghosts_dir.jsonld', '%kernel.cache_dir%/json_streamer/lazy_ghost/jsonld');
996-
$loader->load('json_streamer/hydra.xml');
997996
}
998997

999-
if (isset($formats['json'])) {
1000-
$loader->load('json_streamer/json.xml');
998+
$loader->load('json_streamer/common.xml');
999+
1000+
if ($config['use_symfony_listeners']) {
1001+
$loader->load('json_streamer/events.xml');
1002+
} else {
1003+
if (isset($formats['jsonld'])) {
1004+
$loader->load('json_streamer/hydra.xml');
1005+
}
1006+
1007+
if (isset($formats['json'])) {
1008+
$loader->load('json_streamer/json.xml');
1009+
}
10011010
}
10021011
}
10031012
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" ?>
2+
<container xmlns="http://symfony.com/schema/dic/services"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
5+
<services>
6+
<service id="api_platform.jsonld.json_streamer.stream_writer" class="Symfony\Component\JsonStreamer\JsonStreamWriter">
7+
<argument type="tagged_locator" tag="json_streamer.value_transformer" />
8+
<argument type="service" id="api_platform.jsonld.json_streamer.write.property_metadata_loader" />
9+
<argument>%.json_streamer.stream_writers_dir.jsonld%</argument>
10+
</service>
11+
12+
<service id="api_platform.jsonld.json_streamer.stream_reader" class="Symfony\Component\JsonStreamer\JsonStreamReader">
13+
<argument type="tagged_locator" tag="json_streamer.value_transformer" />
14+
<argument type="service" id="json_streamer.read.property_metadata_loader" />
15+
<argument>%.json_streamer.stream_readers_dir.jsonld%</argument>
16+
<argument>%.json_streamer.lazy_ghosts_dir.jsonld%</argument>
17+
</service>
18+
19+
<service id="api_platform.jsonld.json_streamer.write.property_metadata_loader" class="ApiPlatform\JsonLd\JsonStreamer\WritePropertyMetadataLoader">
20+
<argument type="service" id="json_streamer.write.property_metadata_loader" />
21+
<argument type="service" id="api_platform.resource_class_resolver" />
22+
</service>
23+
24+
<service id="api_platform.jsonld.json_streamer.write.value_transformer.iri" class="ApiPlatform\JsonLd\JsonStreamer\ValueTransformer\IriValueTransformer">
25+
<argument type="service" id="api_platform.iri_converter" />
26+
<tag name="json_streamer.value_transformer"/>
27+
</service>
28+
29+
<service id="api_platform.jsonld.json_streamer.write.value_transformer.type" class="ApiPlatform\JsonLd\JsonStreamer\ValueTransformer\TypeValueTransformer">
30+
<tag name="json_streamer.value_transformer"/>
31+
</service>
32+
33+
<service id="api_platform.jsonld.json_streamer.write.value_transformer.context" class="ApiPlatform\JsonLd\JsonStreamer\ValueTransformer\ContextValueTransformer">
34+
<argument type="service" id="api_platform.router" />
35+
<tag name="json_streamer.value_transformer"/>
36+
</service>
37+
38+
</services>
39+
</container>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?xml version="1.0" ?>
2+
<container xmlns="http://symfony.com/schema/dic/services"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
5+
<services>
6+
<service id="api_platform.jsonld.state_processor.json_streamer" class="ApiPlatform\Hydra\State\JsonStreamerProcessor">
7+
<argument>null</argument>
8+
<argument type="service" id="api_platform.jsonld.json_streamer.stream_writer" />
9+
<argument type="service" id="api_platform.iri_converter" />
10+
<argument type="service" id="api_platform.resource_class_resolver" />
11+
<argument type="service" id="api_platform.metadata.operation.metadata_factory" />
12+
<argument>%api_platform.collection.pagination.page_parameter_name%</argument>
13+
<argument>%api_platform.collection.pagination.enabled_parameter_name%</argument>
14+
<argument>%api_platform.url_generation_strategy%</argument>
15+
</service>
16+
17+
<service id="api_platform.jsonld.state_provider.json_streamer" class="ApiPlatform\Hydra\State\JsonStreamerProvider">
18+
<argument>null</argument>
19+
<argument type="service" id="api_platform.jsonld.json_streamer.stream_reader" />
20+
</service>
21+
22+
<service id="api_platform.state_processor.json_streamer" class="ApiPlatform\Serializer\State\JsonStreamerProcessor">
23+
<argument>null</argument>
24+
<argument type="service" id="json_streamer.stream_writer" />
25+
<argument type="service" id="api_platform.iri_converter" />
26+
<argument type="service" id="api_platform.resource_class_resolver" />
27+
<argument type="service" id="api_platform.metadata.operation.metadata_factory" />
28+
</service>
29+
30+
<service id="api_platform.state_provider.json_streamer" class="ApiPlatform\Serializer\State\JsonStreamerProvider">
31+
<argument>null</argument>
32+
<argument type="service" id="json_streamer.stream_reader" />
33+
</service>
34+
35+
<service id="api_platform.listener.request.json_streamer_deserialize" class="ApiPlatform\Symfony\EventListener\JsonStreamerDeserializeListener">
36+
<argument type="service" id="api_platform.state_provider.json_streamer" />
37+
<argument>json</argument>
38+
<argument type="service" id="api_platform.metadata.resource.metadata_collection_factory" />
39+
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="3" />
40+
</service>
41+
42+
<service id="api_platform.listener.request.jsonld_streamer_deserialize" class="ApiPlatform\Symfony\EventListener\JsonStreamerDeserializeListener">
43+
<argument type="service" id="api_platform.jsonld.state_provider.json_streamer" />
44+
<argument>jsonld</argument>
45+
<argument type="service" id="api_platform.metadata.resource.metadata_collection_factory" />
46+
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="3" />
47+
</service>
48+
49+
<service id="api_platform.listener.view.json_streamer_serialize" class="ApiPlatform\Symfony\EventListener\JsonStreamerSerializeListener">
50+
<argument type="service" id="api_platform.state_processor.json_streamer" />
51+
<argument>json</argument>
52+
<argument type="service" id="api_platform.metadata.resource.metadata_collection_factory" />
53+
<tag name="kernel.event_listener" event="kernel.view" method="onKernelView" priority="17" />
54+
</service>
55+
56+
<service id="api_platform.listener.view.jsonld_streamer_serialize" class="ApiPlatform\Symfony\EventListener\JsonStreamerSerializeListener">
57+
<argument type="service" id="api_platform.jsonld.state_processor.json_streamer" />
58+
<argument>jsonld</argument>
59+
<argument type="service" id="api_platform.metadata.resource.metadata_collection_factory" />
60+
<tag name="kernel.event_listener" event="kernel.view" method="onKernelView" priority="17" />
61+
</service>
62+
</services>
63+
</container>

src/Symfony/Bundle/Resources/config/json_streamer/hydra.xml

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,6 @@
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
55
<services>
6-
<service id="api_platform.jsonld.json_streamer.stream_writer" class="Symfony\Component\JsonStreamer\JsonStreamWriter">
7-
<argument type="tagged_locator" tag="json_streamer.value_transformer" />
8-
<argument type="service" id="api_platform.jsonld.json_streamer.write.property_metadata_loader" />
9-
<argument>%.json_streamer.stream_writers_dir.jsonld%</argument>
10-
</service>
11-
12-
<service id="api_platform.jsonld.json_streamer.stream_reader" class="Symfony\Component\JsonStreamer\JsonStreamReader">
13-
<argument type="tagged_locator" tag="json_streamer.value_transformer" />
14-
<argument type="service" id="json_streamer.read.property_metadata_loader" />
15-
<argument>%.json_streamer.stream_readers_dir.jsonld%</argument>
16-
<argument>%.json_streamer.lazy_ghosts_dir.jsonld%</argument>
17-
</service>
18-
19-
<service id="api_platform.jsonld.json_streamer.write.property_metadata_loader" class="ApiPlatform\JsonLd\JsonStreamer\WritePropertyMetadataLoader">
20-
<argument type="service" id="json_streamer.write.property_metadata_loader" />
21-
<argument type="service" id="api_platform.resource_class_resolver" />
22-
</service>
23-
24-
<service id="api_platform.jsonld.json_streamer.write.value_transformer.iri" class="ApiPlatform\JsonLd\JsonStreamer\ValueTransformer\IriValueTransformer">
25-
<argument type="service" id="api_platform.iri_converter" />
26-
<tag name="json_streamer.value_transformer"/>
27-
</service>
28-
29-
<service id="api_platform.jsonld.json_streamer.write.value_transformer.type" class="ApiPlatform\JsonLd\JsonStreamer\ValueTransformer\TypeValueTransformer">
30-
<tag name="json_streamer.value_transformer"/>
31-
</service>
32-
33-
<service id="api_platform.jsonld.json_streamer.write.value_transformer.context" class="ApiPlatform\JsonLd\JsonStreamer\ValueTransformer\ContextValueTransformer">
34-
<argument type="service" id="api_platform.router" />
35-
<tag name="json_streamer.value_transformer"/>
36-
</service>
37-
386
<service id="api_platform.jsonld.state_processor.json_streamer" class="ApiPlatform\Hydra\State\JsonStreamerProcessor" decorates="api_platform.state_processor.main" decoration-priority="190">
397
<argument type="service" id="api_platform.jsonld.state_processor.json_streamer.inner" />
408
<argument type="service" id="api_platform.jsonld.json_streamer.stream_writer" />
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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\Symfony\EventListener;
15+
16+
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
17+
use ApiPlatform\State\ProviderInterface;
18+
use ApiPlatform\State\Util\OperationRequestInitiatorTrait;
19+
use ApiPlatform\State\Util\RequestAttributesExtractor;
20+
use Symfony\Component\HttpKernel\Event\RequestEvent;
21+
22+
/**
23+
* Deserializes the data sent in the requested format using JSON Streamer.
24+
*
25+
* @author Kévin Dunglas <[email protected]>
26+
*/
27+
final class JsonStreamerDeserializeListener
28+
{
29+
use OperationRequestInitiatorTrait;
30+
31+
/**
32+
* @param ProviderInterface<object> $jsonStreamerProvider
33+
*/
34+
public function __construct(
35+
private ProviderInterface $jsonStreamerProvider,
36+
private readonly string $format,
37+
?ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null,
38+
) {
39+
$this->resourceMetadataCollectionFactory = $resourceMetadataFactory;
40+
}
41+
42+
/**
43+
* Deserializes the data sent in the requested format.
44+
*/
45+
public function onKernelRequest(RequestEvent $event): void
46+
{
47+
$request = $event->getRequest();
48+
$operation = $this->initializeOperation($request);
49+
50+
if (
51+
!($attributes = RequestAttributesExtractor::extractAttributes($request))
52+
|| !$attributes['receive']
53+
|| !$operation
54+
|| !$operation->getJsonStream()
55+
|| $this->format !== $request->attributes->get('input_format')
56+
) {
57+
return;
58+
}
59+
60+
$data = $this->jsonStreamerProvider->provide($operation, $request->attributes->get('_api_uri_variables') ?? [], [
61+
'request' => $request,
62+
'uri_variables' => $request->attributes->get('_api_uri_variables') ?? [],
63+
'resource_class' => $operation->getClass(),
64+
]);
65+
66+
$request->attributes->set('data', $data);
67+
}
68+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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\Symfony\EventListener;
15+
16+
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
17+
use ApiPlatform\State\ProcessorInterface;
18+
use ApiPlatform\State\Util\OperationRequestInitiatorTrait;
19+
use ApiPlatform\State\Util\RequestAttributesExtractor;
20+
use Symfony\Component\HttpFoundation\Response;
21+
use Symfony\Component\HttpKernel\Event\ViewEvent;
22+
23+
/**
24+
* Serializes data using JSON Streamer.
25+
*
26+
* @author Kévin Dunglas <[email protected]>
27+
*/
28+
final class JsonStreamerSerializeListener
29+
{
30+
use OperationRequestInitiatorTrait;
31+
32+
/**
33+
* @param ProcessorInterface<mixed,Response> $jsonStreamerProcessor
34+
*/
35+
public function __construct(private readonly ProcessorInterface $jsonStreamerProcessor, private readonly string $format, ?ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null)
36+
{
37+
$this->resourceMetadataCollectionFactory = $resourceMetadataFactory;
38+
}
39+
40+
/**
41+
* Creates a Response to send to the client according to the requested format.
42+
*/
43+
public function onKernelView(ViewEvent $event): void
44+
{
45+
$request = $event->getRequest();
46+
$operation = $this->initializeOperation($request);
47+
48+
$attributes = RequestAttributesExtractor::extractAttributes($request);
49+
if (!($attributes['respond'] ?? $request->attributes->getBoolean('_api_respond')) || !$operation || !$operation->getJsonStream() || $this->format !== $request->getRequestFormat()) {
50+
return;
51+
}
52+
53+
$uriVariables = $request->attributes->get('_api_uri_variables') ?? [];
54+
$response = $this->jsonStreamerProcessor->process($event->getControllerResult(), $operation, $uriVariables, [
55+
'request' => $request,
56+
'uri_variables' => $uriVariables,
57+
'resource_class' => $operation->getClass(),
58+
'original_data' => $request->attributes->get('original_data'),
59+
]);
60+
61+
$event->setResponse($response);
62+
}
63+
}

0 commit comments

Comments
 (0)