Completed
Push — develop ( 960a7a...f8a065 )
by Baptiste
06:45
created

ResourceController   C

Complexity

Total Complexity 10

Size/Duplication

Total Lines 132
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 20

Test Coverage

Coverage 95.16%

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 20
dl 0
loc 132
ccs 59
cts 62
cp 0.9516
rs 6.4705
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 22 3
B listAction() 0 66 6
B optionsAction() 0 32 1
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Rest\ServerBundle\Controller;
5
6
use Innmind\Rest\ServerBundle\{
7
    Format,
8
    Exception\InvalidArgumentException
9
};
10
use Innmind\Rest\Server\{
11
    RangeExtractor\ExtractorInterface,
12
    SpecificationBuilder\BuilderInterface,
13
    Response\HeaderBuilder\ListBuilderInterface,
14
    GatewayInterface,
15
    Request\Range,
16
    Exception\RangeNotFoundException,
17
    Exception\NoFilterFoundException
18
};
19
use Innmind\Http\{
20
    Message\ResponseInterface,
21
    Message\Response,
22
    Message\StatusCode,
23
    Message\ReasonPhrase,
24
    Headers,
25
    Header\HeaderInterface,
26
    Header\ContentType,
27
    Header\ContentTypeValue,
28
    Header\ParameterInterface,
29
    Exception\Http\RangeNotSatisfiableException
30
};
31
use Innmind\Filesystem\Stream\StringStream;
32
use Innmind\Immutable\{
33
    Map,
34
    MapInterface
35
};
36
use Symfony\Component\{
37
    HttpFoundation\Request,
38
    Serializer\SerializerInterface
39
};
40
41
final class ResourceController
42
{
43
    private $format;
44
    private $serializer;
45
    private $rangeExtractor;
46
    private $specificationBuilder;
47
    private $gateways;
48
    private $listHeaderBuilder;
49
50 4
    public function __construct(
51
        Format $format,
52
        SerializerInterface $serializer,
53
        ExtractorInterface $rangeExtractor,
54
        BuilderInterface $specificationBuilder,
55
        MapInterface $gateways,
56
        ListBuilderInterface $listHeaderBuilder
57
    ) {
58
        if (
59 4
            (string) $gateways->keyType() !== 'string' ||
60 4
            (string) $gateways->valueType() !== GatewayInterface::class
61
        ) {
62
            throw new InvalidArgumentException;
63
        }
64
65 4
        $this->format = $format;
66 4
        $this->serializer = $serializer;
67 4
        $this->rangeExtractor = $rangeExtractor;
68 4
        $this->specificationBuilder = $specificationBuilder;
69 4
        $this->gateways = $gateways;
70 4
        $this->listHeaderBuilder = $listHeaderBuilder;
71 4
    }
72
73 3
    public function listAction(Request $request): ResponseInterface
74
    {
75 3
        $definition = $request->attributes->get('_innmind_resource_definition');
76 3
        $request = $request->attributes->get('_innmind_request');
77
78
        try {
79 3
            $range = $this->rangeExtractor->extract($request);
80 1
        } catch (RangeNotFoundException $e) {
81 1
            $range = null;
82
        }
83
84
        try {
85 3
            $specification = $this->specificationBuilder->buildFrom(
86
                $request,
87
                $definition
88
            );
89
        } catch (NoFilterFoundException $e) {
90
            $specification = null;
91
        }
92
93
        $accessor = $this
94 3
            ->gateways
95 3
            ->get((string) $definition->gateway())
96 3
            ->resourceListAccessor();
97 3
        $identities = $accessor(
98
            $definition,
99
            $specification,
100
            $range
101
        );
102
103
        if (
104 3
            $identities->size() === 0 &&
105 3
            $range instanceof Range
106
        ) {
107 1
            throw new RangeNotSatisfiableException;
108
        }
109
110 2
        return new Response(
111 2
            $code = new StatusCode(StatusCode::codes()->get(
112 2
                $range instanceof Range ? 'PARTIAL_CONTENT' : 'OK'
113
            )),
114 2
            new ReasonPhrase(ReasonPhrase::defaults()->get($code->value())),
115 2
            $request->protocolVersion(),
116 2
            new Headers(
117 2
                $this->listHeaderBuilder->build(
118
                    $identities,
119
                    $request,
120
                    $definition,
121
                    $specification,
122
                    $range
123
                )
124
            ),
125 2
            new StringStream(
126 2
                $this->serializer->serialize(
127
                    $identities,
128 2
                    $this->format->acceptable($request)->name(),
129
                    [
130 2
                        'request' => $request,
131 2
                        'definition' => $definition,
132 2
                        'specification' => $specification,
133 2
                        'range' => $range,
134
                    ]
135
                )
136
            )
137
        );
138
    }
139
140 1
    public function optionsAction(Request $request): ResponseInterface
141
    {
142 1
        $definition = $request->attributes->get('_innmind_resource_definition');
143 1
        $request = $request->attributes->get('_innmind_request');
144 1
        $format = $this->format->acceptable($request);
145 1
        $mediaType = $format->preferredMediaType();
146
147 1
        return new Response(
148 1
            $code = new StatusCode(StatusCode::codes()->get('OK')),
149 1
            new ReasonPhrase(ReasonPhrase::defaults()->get($code->value())),
150 1
            $request->protocolVersion(),
151 1
            new Headers(
152 1
                (new Map('string', HeaderInterface::class))
153 1
                    ->put(
154 1
                        'Content-Type',
155 1
                        new ContentType(
156 1
                            new ContentTypeValue(
157 1
                                $mediaType->topLevel(),
158 1
                                $mediaType->subType(),
159 1
                                new Map('string', ParameterInterface::class)
160
                            )
161
                        )
162
                    )
163
            ),
164 1
            new StringStream(
165 1
                $this->serializer->serialize(
166
                    $definition,
167 1
                    $format->name()
168
                )
169
            )
170
        );
171
    }
172
}
173