Issues (3641)

Formatter/Response/ResponseFormatter.php (1 issue)

1
<?php
2
3
/**
4
 * Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
5
 * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
6
 */
7
8
namespace Spryker\Glue\GlueApplication\Formatter\Response;
9
10
use Generated\Shared\Transfer\GlueRequestTransfer;
11
use Generated\Shared\Transfer\GlueResourceMethodCollectionTransfer;
12
use Generated\Shared\Transfer\GlueResponseTransfer;
13
use Spryker\Glue\GlueApplication\Encoder\Response\ResponseEncoderStrategyInterface;
14
use Spryker\Glue\GlueApplication\GlueApplicationConfig;
15
use Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceInterface;
16
use Symfony\Component\HttpFoundation\Request as HttpRequest;
17
use Symfony\Component\HttpFoundation\Response;
18
19
class ResponseFormatter implements ResponseFormatterInterface
20
{
21
    /**
22
     * @var array<string, \Spryker\Glue\GlueApplication\Encoder\Response\ResponseEncoderStrategyInterface>
23
     */
24
    protected array $responseEncoderStrategies = [];
25
26
    /**
27
     * @var \Spryker\Glue\GlueApplication\GlueApplicationConfig
28
     */
29
    protected GlueApplicationConfig $glueApplicationConfig;
30
31
    /**
32
     * @param array<\Spryker\Glue\GlueApplication\Encoder\Response\ResponseEncoderStrategyInterface> $responseEncoderStrategies
33
     * @param \Spryker\Glue\GlueApplication\GlueApplicationConfig $glueApplicationConfig
34
     */
35
    public function __construct(
36
        array $responseEncoderStrategies,
37
        GlueApplicationConfig $glueApplicationConfig
38
    ) {
39
        array_map(function (ResponseEncoderStrategyInterface $responseEncoderStrategy): void {
40
            $this->responseEncoderStrategies[$responseEncoderStrategy->getAcceptedType()] = $responseEncoderStrategy;
41
        }, $responseEncoderStrategies);
42
43
        $this->glueApplicationConfig = $glueApplicationConfig;
44
    }
45
46
    /**
47
     * @param \Generated\Shared\Transfer\GlueResponseTransfer $glueResponseTransfer
48
     * @param \Generated\Shared\Transfer\GlueRequestTransfer $glueRequestTransfer
49
     * @param \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceInterface|null $resource
50
     *
51
     * @return \Generated\Shared\Transfer\GlueResponseTransfer
52
     */
53
    public function format(
54
        GlueResponseTransfer $glueResponseTransfer,
55
        GlueRequestTransfer $glueRequestTransfer,
56
        ?ResourceInterface $resource = null
57
    ): GlueResponseTransfer {
58
        if (!$glueResponseTransfer->getHttpStatus()) {
59
            $glueResponseTransfer->setHttpStatus($this->getStatusCode($glueRequestTransfer));
60
        }
61
62
        if ($glueResponseTransfer->getContent()) {
63
            return $glueResponseTransfer;
64
        }
65
66
        if (!array_key_exists($glueRequestTransfer->getAcceptedFormat(), $this->responseEncoderStrategies)) {
67
            $glueRequestTransfer->setAcceptedFormat(
68
                $this->glueApplicationConfig->getDefaultResponseFormat(),
69
            );
70
        }
71
72
        $isSnakeCased = $this->getIsSnakeCased($glueRequestTransfer, $resource);
73
        $isSingularResponse = $this->getIsSingularResponse($glueRequestTransfer, $resource);
74
        $data = $this->expandData($glueResponseTransfer, $isSnakeCased, $isSingularResponse);
75
76
        return $this->formatResponse($glueResponseTransfer, $glueRequestTransfer->getAcceptedFormat(), $data);
77
    }
78
79
    /**
80
     * @param \Generated\Shared\Transfer\GlueResponseTransfer $glueResponseTransfer
81
     * @param string $format
82
     * @param array<mixed> $data
83
     *
84
     * @return \Generated\Shared\Transfer\GlueResponseTransfer
85
     */
86
    protected function formatResponse(
87
        GlueResponseTransfer $glueResponseTransfer,
88
        string $format,
89
        array $data
90
    ): GlueResponseTransfer {
91
        if (array_key_exists($format, $this->responseEncoderStrategies)) {
92
            return $this->responseEncoderStrategies[$format]->encode($data, $glueResponseTransfer);
93
        }
94
95
        return $glueResponseTransfer;
96
    }
97
98
    /**
99
     * @param \Generated\Shared\Transfer\GlueResponseTransfer $glueResponseTransfer
100
     * @param bool $isSnakeCased
101
     * @param bool $isSingularResponse
102
     *
103
     * @return array<mixed>
104
     */
105
    protected function expandData(
106
        GlueResponseTransfer $glueResponseTransfer,
107
        bool $isSnakeCased,
108
        bool $isSingularResponse
109
    ): array {
110
        $data = [];
111
112
        if ($glueResponseTransfer->getErrors()->count()) {
113
            foreach ($glueResponseTransfer->getErrors() as $glueErrorTransfer) {
114
                $data[] = $glueErrorTransfer->toArray(true, !$isSnakeCased);
115
            }
116
117
            return $data;
118
        }
119
120
        if ($this->glueApplicationConfig->isConfigurableResponseEnabled() === true && $isSingularResponse === true) {
0 ignored issues
show
The condition $this->glueApplicationCo...ponseEnabled() === true is always false.
Loading history...
121
            return $glueResponseTransfer->getResources()
122
                ->offsetGet(0)
123
                ->getAttributesOrFail()
124
                ->toArray(true, !$isSnakeCased);
125
        }
126
127
        return $this->getDataWithMultiResources($glueResponseTransfer, $isSnakeCased);
128
    }
129
130
    /**
131
     * @deprecated Exists for BC reasons. Will be removed in the next major release.
132
     *
133
     * @param \Generated\Shared\Transfer\GlueResponseTransfer $glueResponseTransfer
134
     * @param bool $isSnakeCased
135
     *
136
     * @return array<mixed>
137
     */
138
    protected function getDataWithMultiResources(
139
        GlueResponseTransfer $glueResponseTransfer,
140
        bool $isSnakeCased
141
    ): array {
142
        $data = [];
143
144
        foreach ($glueResponseTransfer->getResources() as $resource) {
145
            $data[] = $resource->getAttributesOrFail()->toArray(true, !$isSnakeCased);
146
        }
147
148
        return $data;
149
    }
150
151
    /**
152
     * @param \Generated\Shared\Transfer\GlueRequestTransfer $glueRequestTransfer
153
     *
154
     * @return int
155
     */
156
    protected function getStatusCode(GlueRequestTransfer $glueRequestTransfer): int
157
    {
158
        switch ($glueRequestTransfer->getMethod()) {
159
            case HttpRequest::METHOD_GET:
160
            case HttpRequest::METHOD_PATCH:
161
                return Response::HTTP_OK;
162
            case HttpRequest::METHOD_POST:
163
                return Response::HTTP_CREATED;
164
            case HttpRequest::METHOD_DELETE:
165
                return Response::HTTP_NO_CONTENT;
166
        }
167
168
        return Response::HTTP_OK;
169
    }
170
171
    /**
172
     * @param \Generated\Shared\Transfer\GlueRequestTransfer $glueRequestTransfer
173
     * @param \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceInterface|null $resource
174
     * @param string $propertyName
175
     *
176
     * @return bool
177
     */
178
    protected function getMethodProperty(
179
        GlueRequestTransfer $glueRequestTransfer,
180
        ?ResourceInterface $resource,
181
        string $propertyName
182
    ): bool {
183
        if ($resource === null) {
184
            return false;
185
        }
186
187
        if ($glueRequestTransfer->getResource() === null) {
188
            return false;
189
        }
190
191
        $method = $glueRequestTransfer->getResourceOrFail()->getMethodOrFail();
192
        $declaredMethods = $resource->getDeclaredMethods();
193
194
        if (!$this->hasDeclaredMethods($declaredMethods, $method)) {
195
            return false;
196
        }
197
198
        return (bool)$declaredMethods->offsetGet($method)->$propertyName();
199
    }
200
201
    /**
202
     * @param \Generated\Shared\Transfer\GlueRequestTransfer $glueRequestTransfer
203
     * @param \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceInterface|null $resource
204
     *
205
     * @return bool
206
     */
207
    protected function getIsSnakeCased(
208
        GlueRequestTransfer $glueRequestTransfer,
209
        ?ResourceInterface $resource = null
210
    ): bool {
211
        return $this->getMethodProperty($glueRequestTransfer, $resource, 'getIsSnakeCased');
212
    }
213
214
    /**
215
     * @param \Generated\Shared\Transfer\GlueRequestTransfer $glueRequestTransfer
216
     * @param \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceInterface|null $resource
217
     *
218
     * @return bool
219
     */
220
    protected function getIsSingularResponse(
221
        GlueRequestTransfer $glueRequestTransfer,
222
        ?ResourceInterface $resource = null
223
    ): bool {
224
        return $this->getMethodProperty($glueRequestTransfer, $resource, 'getIsSingularResponse');
225
    }
226
227
    /**
228
     * @param \Generated\Shared\Transfer\GlueResourceMethodCollectionTransfer $declaredMethods
229
     * @param string $method
230
     *
231
     * @return bool
232
     */
233
    protected function hasDeclaredMethods(
234
        GlueResourceMethodCollectionTransfer $declaredMethods,
235
        string $method
236
    ): bool {
237
        if (
238
            !$declaredMethods->offsetExists($method) ||
239
            $declaredMethods->offsetGet($method) === null
240
        ) {
241
            return false;
242
        }
243
244
        return true;
245
    }
246
}
247