Passed
Push — master ( 8bd912...d93388 )
by Alan
06:58 queued 02:20
created

Bundle/DataCollector/RequestDataCollector.php (8 issues)

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\Core\Bridge\Symfony\Bundle\DataCollector;
15
16
use ApiPlatform\Core\Bridge\Symfony\Bundle\DataPersister\TraceableChainDataPersister;
17
use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainCollectionDataProvider;
18
use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainItemDataProvider;
19
use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainSubresourceDataProvider;
20
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
21
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
22
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
23
use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface;
24
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
25
use ApiPlatform\Core\Util\RequestAttributesExtractor;
26
use Psr\Container\ContainerInterface;
27
use Symfony\Component\HttpFoundation\Request;
28
use Symfony\Component\HttpFoundation\Response;
29
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
30
31
/**
32
 * @author Julien DENIAU <[email protected]>
33
 * @author Anthony GRASSIOT <[email protected]>
34
 */
35
final class RequestDataCollector extends DataCollector
36
{
37
    private $metadataFactory;
38
    private $filterLocator;
39
    private $collectionDataProvider;
40
    private $itemDataProvider;
41
    private $subresourceDataProvider;
42
    private $dataPersister;
43
44
    public function __construct(ResourceMetadataFactoryInterface $metadataFactory, ContainerInterface $filterLocator, CollectionDataProviderInterface $collectionDataProvider = null, ItemDataProviderInterface $itemDataProvider = null, SubresourceDataProviderInterface $subresourceDataProvider = null, DataPersisterInterface $dataPersister = null)
45
    {
46
        $this->metadataFactory = $metadataFactory;
47
        $this->filterLocator = $filterLocator;
48
        $this->collectionDataProvider = $collectionDataProvider;
49
        $this->itemDataProvider = $itemDataProvider;
50
        $this->subresourceDataProvider = $subresourceDataProvider;
51
        $this->dataPersister = $dataPersister;
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    public function collect(Request $request, Response $response, \Exception $exception = null)
58
    {
59
        $counters = ['ignored_filters' => 0];
60
        $resourceClass = $request->attributes->get('_api_resource_class');
61
        $resourceMetadata = $resourceClass ? $this->metadataFactory->create($resourceClass) : null;
62
63
        $filters = [];
64
        foreach ($resourceMetadata ? $resourceMetadata->getAttribute('filters', []) : [] as $id) {
65
            if ($this->filterLocator->has($id)) {
66
                $filters[$id] = \get_class($this->filterLocator->get($id));
67
                continue;
68
            }
69
70
            $filters[$id] = null;
71
            ++$counters['ignored_filters'];
72
        }
73
74
        $this->data = [
75
            'resource_class' => $resourceClass,
76
            'resource_metadata' => $resourceMetadata ? $this->cloneVar($resourceMetadata) : null,
77
            'acceptable_content_types' => $request->getAcceptableContentTypes(),
78
            'request_attributes' => RequestAttributesExtractor::extractAttributes($request),
79
            'filters' => $filters,
80
            'counters' => $counters,
81
            'dataProviders' => [],
82
            'dataPersisters' => ['responses' => []],
83
        ];
84
85
        if ($this->collectionDataProvider instanceof TraceableChainCollectionDataProvider) {
86
            $this->data['dataProviders']['collection'] = [
87
                'context' => $this->cloneVar($this->collectionDataProvider->getContext()),
88
                'responses' => $this->collectionDataProvider->getProvidersResponse(),
89
            ];
90
        }
91
92
        if ($this->itemDataProvider instanceof TraceableChainItemDataProvider) {
93
            $this->data['dataProviders']['item'] = [
94
                'context' => $this->cloneVar($this->itemDataProvider->getContext()),
95
                'responses' => $this->itemDataProvider->getProvidersResponse(),
96
            ];
97
        }
98
99
        if ($this->subresourceDataProvider instanceof TraceableChainSubresourceDataProvider) {
100
            $this->data['dataProviders']['subresource'] = [
101
                'context' => $this->cloneVar($this->subresourceDataProvider->getContext()),
102
                'responses' => $this->subresourceDataProvider->getProvidersResponse(),
103
            ];
104
        }
105
106
        if ($this->dataPersister instanceof TraceableChainDataPersister) {
107
            $this->data['dataPersisters']['responses'] = $this->dataPersister->getPersistersResponse();
108
        }
109
    }
110
111
    public function getAcceptableContentTypes(): array
112
    {
113
        return $this->data['acceptable_content_types'] ?? [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->data['acce...tent_types'] ?? array() could return the type Symfony\Component\VarDumper\Cloner\Data which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
114
    }
115
116
    public function getResourceClass()
117
    {
118
        return $this->data['resource_class'] ?? null;
119
    }
120
121
    public function getResourceMetadata()
122
    {
123
        return $this->data['resource_metadata'] ?? null;
124
    }
125
126
    public function getRequestAttributes(): array
127
    {
128
        return $this->data['request_attributes'] ?? [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->data['requ...attributes'] ?? array() could return the type Symfony\Component\VarDumper\Cloner\Data which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
129
    }
130
131
    public function getFilters(): array
132
    {
133
        return $this->data['filters'] ?? [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->data['filters'] ?? array() could return the type Symfony\Component\VarDumper\Cloner\Data which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
134
    }
135
136
    public function getCounters(): array
137
    {
138
        return $this->data['counters'] ?? [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->data['counters'] ?? array() could return the type Symfony\Component\VarDumper\Cloner\Data which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
139
    }
140
141
    public function getCollectionDataProviders(): array
142
    {
143
        return $this->data['dataProviders']['collection'] ?? ['context' => [], 'responses' => []];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->data['data...'responses' => array()) could return the type Symfony\Component\VarDumper\Cloner\Data which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
144
    }
145
146
    public function getItemDataProviders(): array
147
    {
148
        return $this->data['dataProviders']['item'] ?? ['context' => [], 'responses' => []];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->data['data...'responses' => array()) could return the type Symfony\Component\VarDumper\Cloner\Data which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
149
    }
150
151
    public function getSubresourceDataProviders(): array
152
    {
153
        return $this->data['dataProviders']['subresource'] ?? ['context' => [], 'responses' => []];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->data['data...'responses' => array()) could return the type Symfony\Component\VarDumper\Cloner\Data which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
154
    }
155
156
    public function getDataPersisters(): array
157
    {
158
        return $this->data['dataPersisters'] ?? ['responses' => []];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->data['data...'responses' => array()) could return the type Symfony\Component\VarDumper\Cloner\Data which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164
    public function getName(): string
165
    {
166
        return 'api_platform.data_collector.request';
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     */
172
    public function reset()
173
    {
174
        $this->data = [];
175
    }
176
}
177