• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 16531587208

25 Jul 2025 09:05PM UTC coverage: 0.0% (-22.1%) from 22.07%
16531587208

Pull #7225

github

web-flow
Merge 23f449a58 into 02a764950
Pull Request #7225: feat: json streamer

0 of 294 new or added lines in 31 files covered. (0.0%)

11514 existing lines in 375 files now uncovered.

0 of 51976 relevant lines covered (0.0%)

0.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Hydra/State/JsonStreamerProcessor.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
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\Hydra\State;
15

16
use ApiPlatform\Hydra\Collection;
17
use ApiPlatform\Hydra\IriTemplate;
18
use ApiPlatform\Hydra\IriTemplateMapping;
19
use ApiPlatform\Hydra\PartialCollectionView;
20
use ApiPlatform\Metadata\CollectionOperationInterface;
21
use ApiPlatform\Metadata\Error;
22
use ApiPlatform\Metadata\HttpOperation;
23
use ApiPlatform\Metadata\IriConverterInterface;
24
use ApiPlatform\Metadata\Operation;
25
use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface;
26
use ApiPlatform\Metadata\QueryParameterInterface;
27
use ApiPlatform\Metadata\ResourceClassResolverInterface;
28
use ApiPlatform\Metadata\UrlGeneratorInterface;
29
use ApiPlatform\Metadata\Util\IriHelper;
30
use ApiPlatform\State\Pagination\PartialPaginatorInterface;
31
use ApiPlatform\State\Util\HttpResponseStatusTrait;
32
use ApiPlatform\State\Pagination\PaginatorInterface;
33
use ApiPlatform\State\ProcessorInterface;
34
use ApiPlatform\State\Util\HttpResponseHeadersTrait;
35
use Symfony\Component\HttpFoundation\Response;
36
use Symfony\Component\HttpFoundation\StreamedResponse;
37
use Symfony\Component\JsonStreamer\StreamWriterInterface;
38
use ApiPlatform\Hydra\State\Util\PaginationHelperTrait;
39
use ApiPlatform\Hydra\State\Util\SearchHelperTrait;
40
use Symfony\Component\TypeInfo\Type;
41

42
/**
43
 * @implements ProcessorInterface<mixed,mixed>
44
 */
45
final class JsonStreamerProcessor implements ProcessorInterface
46
{
47
    use HttpResponseHeadersTrait;
48
    use HttpResponseStatusTrait;
49
    use PaginationHelperTrait;
50
    use SearchHelperTrait;
51

52
    /**
53
     * @param ProcessorInterface<mixed,mixed>            $processor
54
     * @param StreamWriterInterface<array<string,mixed>> $jsonStreamer
55
     */
56
    public function __construct(
57
        private readonly ProcessorInterface $processor,
58
        private readonly StreamWriterInterface $jsonStreamer,
59
        ?IriConverterInterface $iriConverter = null,
60
        ?ResourceClassResolverInterface $resourceClassResolver = null,
61
        ?OperationMetadataFactoryInterface $operationMetadataFactory = null,
62
        private readonly string $pageParameterName = 'page',
63
        private readonly string $enabledParameterName = 'pagination',
64
        private readonly int $urlGenerationStrategy = UrlGeneratorInterface::ABS_PATH,
65
    ) {
NEW
66
        $this->resourceClassResolver = $resourceClassResolver;
×
NEW
67
        $this->iriConverter = $iriConverter;
×
NEW
68
        $this->operationMetadataFactory = $operationMetadataFactory;
×
69
    }
70

71
    public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = [])
72
    {
NEW
73
        if (!$operation->getJsonStream() || !($request = $context['request'] ?? null)) {
×
NEW
74
            return $this->processor->process($data, $operation, $uriVariables, $context);
×
75
        }
76

77
        // TODO: remove this before merging
NEW
78
        if ($request->query->has('skip_json_stream')) {
×
NEW
79
            return $this->processor->process($data, $operation, $uriVariables, $context);
×
80
        }
81

NEW
82
        if ($operation instanceof Error || $data instanceof Response || !$operation instanceof HttpOperation) {
×
NEW
83
            return $this->processor->process($data, $operation, $uriVariables, $context);
×
84
        }
85

NEW
86
        if ($operation instanceof CollectionOperationInterface) {
×
NEW
87
            $requestUri = $request->getRequestUri() ?? '';
×
NEW
88
            $collection = new Collection();
×
NEW
89
            $collection->member = $data;
×
NEW
90
            $collection->view = $this->getView($data, $requestUri, $operation);
×
91

NEW
92
            if ($operation->getParameters()) {
×
NEW
93
                $parts = parse_url($requestUri);
×
NEW
94
                $collection->search = $this->getSearch($parts['path'] ?? '', $operation);
×
95
            }
96

NEW
97
            if ($data instanceof PaginatorInterface) {
×
NEW
98
                $collection->totalItems = $data->getTotalItems();
×
99
            }
100

NEW
101
            if (\is_array($data) || ($data instanceof \Countable && !$data instanceof PartialPaginatorInterface)) {
×
NEW
102
                $collection->totalItems = \count($data);
×
103
            }
104

NEW
105
            $data = $this->jsonStreamer->write(
×
NEW
106
                $collection,
×
NEW
107
                Type::generic(Type::object($collection::class), Type::object($operation->getClass())),
×
NEW
108
                ['data' => $data, 'operation' => $operation],
×
NEW
109
            );
×
110
        } else {
NEW
111
            $data = $this->jsonStreamer->write($data, Type::object($operation->getClass()), [
×
NEW
112
                'data' => $data,
×
NEW
113
                'operation' => $operation,
×
NEW
114
            ]);
×
115
        }
116

117
        /** @var iterable<string> $data */
NEW
118
        $response = new StreamedResponse(
×
NEW
119
            $data,
×
NEW
120
            $this->getStatus($request, $operation, $context),
×
NEW
121
            $this->getHeaders($request, $operation, $context)
×
NEW
122
        );
×
123

NEW
124
        return $this->processor->process($response, $operation, $uriVariables, $context);
×
125
    }
126

127
    private function getView(mixed $object, string $requestUri, Operation $operation): PartialCollectionView
128
    {
NEW
129
        return $this->getPartialCollectionView($object, $requestUri, $this->pageParameterName, $this->enabledParameterName, $operation->getUrlGenerationStrategy() ?? $this->urlGenerationStrategy);
×
130
    }
131
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc