Issues (3641)

Processor/Reader/ProductReviewReader.php (2 issues)

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\ProductReviewsRestApi\Processor\Reader;
9
10
use Generated\Shared\Transfer\BulkProductReviewSearchRequestTransfer;
11
use Generated\Shared\Transfer\FilterTransfer;
12
use Generated\Shared\Transfer\ProductReviewSearchRequestTransfer;
13
use Generated\Shared\Transfer\ProductReviewTransfer;
14
use Spryker\Glue\GlueApplication\Rest\JsonApi\RestResponseInterface;
15
use Spryker\Glue\GlueApplication\Rest\Request\Data\Page;
16
use Spryker\Glue\GlueApplication\Rest\Request\Data\PageInterface;
17
use Spryker\Glue\GlueApplication\Rest\Request\Data\RestRequestInterface;
18
use Spryker\Glue\GlueApplication\Rest\RequestConstantsInterface;
19
use Spryker\Glue\ProductReviewsRestApi\Dependency\Client\ProductReviewsRestApiToProductReviewClientInterface;
20
use Spryker\Glue\ProductReviewsRestApi\Dependency\Client\ProductReviewsRestApiToProductStorageClientInterface;
21
use Spryker\Glue\ProductReviewsRestApi\Processor\RestResponseBuilder\ProductReviewRestResponseBuilderInterface;
22
use Spryker\Glue\ProductReviewsRestApi\ProductReviewsRestApiConfig;
23
use Symfony\Component\HttpFoundation\Response;
24
25
class ProductReviewReader implements ProductReviewReaderInterface
26
{
27
    /**
28
     * @var string
29
     */
30
    protected const PRODUCT_ABSTRACT_MAPPING_TYPE = 'sku';
31
32
    /**
33
     * @var string
34
     */
35
    protected const KEY_ID_PRODUCT_ABSTRACT = 'id_product_abstract';
36
37
    /**
38
     * @var string
39
     */
40
    protected const KEY_SKU = 'sku';
41
42
    /**
43
     * @uses \Spryker\Client\ProductReview\Plugin\Elasticsearch\ResultFormatter\ProductReviewsResultFormatterPlugin::NAME
44
     *
45
     * @var string
46
     */
47
    protected const PRODUCT_REVIEWS = 'productReviews';
48
49
    /**
50
     * @uses \Spryker\Client\ProductReview\Plugin\Elasticsearch\ResultFormatter\PaginatedProductReviewsResultFormatterPlugin::NAME
51
     *
52
     * @var string
53
     */
54
    protected const PAGINATION = 'pagination';
55
56
    /**
57
     * @uses \Spryker\Client\ProductReview\Plugin\Elasticsearch\QueryExpander\FilterByReviewIdQueryExpanderPlugin::REQUEST_PARAM_ID_PRODUCT_REVIEW
58
     *
59
     * @var string
60
     */
61
    protected const REQUEST_PARAM_ID_PRODUCT_REVIEW = ProductReviewTransfer::ID_PRODUCT_REVIEW;
62
63
    /**
64
     * @var \Spryker\Glue\ProductReviewsRestApi\Processor\RestResponseBuilder\ProductReviewRestResponseBuilderInterface
65
     */
66
    protected $productReviewRestResponseBuilder;
67
68
    /**
69
     * @var \Spryker\Glue\ProductReviewsRestApi\Dependency\Client\ProductReviewsRestApiToProductStorageClientInterface
70
     */
71
    protected $productStorageClient;
72
73
    /**
74
     * @var \Spryker\Glue\ProductReviewsRestApi\Dependency\Client\ProductReviewsRestApiToProductReviewClientInterface
75
     */
76
    protected $productReviewClient;
77
78
    /**
79
     * @var \Spryker\Glue\ProductReviewsRestApi\ProductReviewsRestApiConfig
80
     */
81
    protected $productReviewsRestApiConfig;
82
83
    /**
84
     * @param \Spryker\Glue\ProductReviewsRestApi\Processor\RestResponseBuilder\ProductReviewRestResponseBuilderInterface $productReviewRestResponseBuilder
85
     * @param \Spryker\Glue\ProductReviewsRestApi\Dependency\Client\ProductReviewsRestApiToProductStorageClientInterface $productStorageClient
86
     * @param \Spryker\Glue\ProductReviewsRestApi\Dependency\Client\ProductReviewsRestApiToProductReviewClientInterface $productReviewClient
87
     * @param \Spryker\Glue\ProductReviewsRestApi\ProductReviewsRestApiConfig $productReviewsRestApiConfig
88
     */
89
    public function __construct(
90
        ProductReviewRestResponseBuilderInterface $productReviewRestResponseBuilder,
91
        ProductReviewsRestApiToProductStorageClientInterface $productStorageClient,
92
        ProductReviewsRestApiToProductReviewClientInterface $productReviewClient,
93
        ProductReviewsRestApiConfig $productReviewsRestApiConfig
94
    ) {
95
        $this->productReviewRestResponseBuilder = $productReviewRestResponseBuilder;
96
        $this->productStorageClient = $productStorageClient;
97
        $this->productReviewClient = $productReviewClient;
98
        $this->productReviewsRestApiConfig = $productReviewsRestApiConfig;
99
    }
100
101
    /**
102
     * @param \Spryker\Glue\GlueApplication\Rest\Request\Data\RestRequestInterface $restRequest
103
     *
104
     * @return \Spryker\Glue\GlueApplication\Rest\JsonApi\RestResponseInterface
105
     */
106
    public function getProductReviews(RestRequestInterface $restRequest): RestResponseInterface
107
    {
108
        $parentResource = $restRequest->findParentResourceByType(ProductReviewsRestApiConfig::RESOURCE_ABSTRACT_PRODUCTS);
109
        if (!$parentResource || !$parentResource->getId()) {
110
            return $this->productReviewRestResponseBuilder->createProductAbstractSkuMissingErrorResponse();
111
        }
112
113
        $productAbstractData = $this->productStorageClient->findProductAbstractStorageDataByMapping(
114
            static::PRODUCT_ABSTRACT_MAPPING_TYPE,
115
            $parentResource->getId(),
116
            $restRequest->getMetadata()->getLocale(),
117
        );
118
119
        if (!$productAbstractData) {
120
            return $this->productReviewRestResponseBuilder->createProductAbstractNotFoundErrorResponse();
121
        }
122
123
        if ($restRequest->getResource()->getId()) {
124
            return $this->getProductReview($productAbstractData, $restRequest->getResource()->getId());
125
        }
126
127
        if (!$restRequest->getPage()) {
128
            $restRequest->setPage(new Page(0, $this->productReviewsRestApiConfig->getDefaultReviewsPerPage()));
129
        }
130
        $productReviews = $this->getProductReviewsInSearch(
131
            $productAbstractData[static::KEY_ID_PRODUCT_ABSTRACT],
132
            $this->createRequestParamsWithPaginationParameters($restRequest->getPage()),
0 ignored issues
show
It seems like $restRequest->getPage() can also be of type null; however, parameter $page of Spryker\Glue\ProductRevi...hPaginationParameters() does only seem to accept Spryker\Glue\GlueApplica...uest\Data\PageInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

132
            $this->createRequestParamsWithPaginationParameters(/** @scrutinizer ignore-type */ $restRequest->getPage()),
Loading history...
133
        );
134
135
        return $this->productReviewRestResponseBuilder->createProductReviewsCollectionRestResponse(
136
            $productReviews[static::PRODUCT_REVIEWS],
137
            $productAbstractData[static::KEY_SKU],
138
            $productReviews[static::PAGINATION]->getNumFound(),
139
            $restRequest->getPage()->getLimit(),
140
        );
141
    }
142
143
    /**
144
     * @param array<int, array<string, mixed>> $productAbstractDataCollection
145
     * @param \Generated\Shared\Transfer\FilterTransfer $filterTransfer
146
     *
147
     * @return array<array<\Spryker\Glue\GlueApplication\Rest\JsonApi\RestResourceInterface>>
148
     */
149
    public function getProductReviewsResourceCollection(array $productAbstractDataCollection, FilterTransfer $filterTransfer): array
150
    {
151
        /** @var array<\Generated\Shared\Transfer\ProductReviewTransfer> $productReviewTransfers */
152
        $productReviewTransfers = $this->getBulkProductReviewsInSearch(
153
            $this->extractProductAbstractIds($productAbstractDataCollection),
154
            $filterTransfer,
155
        )[static::PRODUCT_REVIEWS];
156
157
        $indexedProductReviewTransfers = [];
158
        foreach ($productReviewTransfers as $productReviewTransfer) {
159
            $indexedProductReviewTransfers[$productReviewTransfer->getFkProductAbstract()][] = $productReviewTransfer;
160
        }
161
162
        return $this->productReviewRestResponseBuilder->createRestResourceCollection($indexedProductReviewTransfers, $productAbstractDataCollection);
163
    }
164
165
    /**
166
     * @param array<string, mixed> $productAbstractData
167
     * @param string $resourceId
168
     *
169
     * @return \Spryker\Glue\GlueApplication\Rest\JsonApi\RestResponseInterface
170
     */
171
    protected function getProductReview(array $productAbstractData, string $resourceId): RestResponseInterface
172
    {
173
        $productReviews = $this->getProductReviewsInSearch(
174
            $productAbstractData[static::KEY_ID_PRODUCT_ABSTRACT],
175
            [static::REQUEST_PARAM_ID_PRODUCT_REVIEW => $resourceId],
176
        );
177
        $productReviewTransfers = $productReviews[static::PRODUCT_REVIEWS];
178
        if (!$productReviewTransfers) {
179
            return $this->productReviewRestResponseBuilder->createProductReviewNotFoundErrorResponse($resourceId);
180
        }
181
        $productReviewTransfer = count($productReviewTransfers) > 1
182
            ? $this->findProductReviewTransferByIdProductReview($productReviewTransfers, $resourceId)
183
            : $productReviewTransfers[0];
184
185
        if (!$productReviewTransfer) {
186
            return $this->productReviewRestResponseBuilder->createProductReviewNotFoundErrorResponse($resourceId);
187
        }
188
189
        return $this->productReviewRestResponseBuilder->createProductReviewRestResponse(
190
            $productReviewTransfer,
191
            $productAbstractData[static::KEY_SKU],
192
            Response::HTTP_OK,
193
        );
194
    }
195
196
    /**
197
     * @param int $idProductAbstract
198
     * @param array<string, mixed> $requestParams
199
     *
200
     * @return array
201
     */
202
    protected function getProductReviewsInSearch(int $idProductAbstract, array $requestParams): array
203
    {
204
        return $this->productReviewClient->findProductReviewsInSearch(
205
            (new ProductReviewSearchRequestTransfer())
206
                ->setRequestParams($requestParams)
207
                ->setIdProductAbstract($idProductAbstract),
208
        );
209
    }
210
211
    /**
212
     * @param array<int> $productAbstractIds
213
     * @param \Generated\Shared\Transfer\FilterTransfer $filterTransfer
214
     *
215
     * @return array
216
     */
217
    protected function getBulkProductReviewsInSearch(
218
        array $productAbstractIds,
219
        FilterTransfer $filterTransfer
220
    ): array {
221
        $productReviews = $this->productReviewClient->getBulkProductReviewsFromSearch(
222
            (new BulkProductReviewSearchRequestTransfer())
223
                ->setFilter($filterTransfer)
224
                ->setProductAbstractIds($productAbstractIds),
225
        );
226
227
        return $productReviews;
228
    }
229
230
    /**
231
     * @param \Spryker\Glue\GlueApplication\Rest\Request\Data\PageInterface $page
232
     *
233
     * @return array
234
     */
235
    protected function createRequestParamsWithPaginationParameters(PageInterface $page): array
236
    {
237
        return [
238
            RequestConstantsInterface::QUERY_OFFSET => $page->getOffset(),
239
            RequestConstantsInterface::QUERY_LIMIT => $page->getLimit(),
240
        ];
241
    }
242
243
    /**
244
     * @param list<\Generated\Shared\Transfer\ProductReviewTransfer> $productReviewTransfers
245
     * @param string $idProductReview
246
     *
247
     * @return \Generated\Shared\Transfer\ProductReviewTransfer|null
248
     */
249
    protected function findProductReviewTransferByIdProductReview(array $productReviewTransfers, string $idProductReview): ?ProductReviewTransfer
250
    {
251
        foreach ($productReviewTransfers as $productReviewTransfer) {
252
            if ((string)$productReviewTransfer->getIdProductReviewOrFail() === $idProductReview) {
253
                return $productReviewTransfer;
254
            }
255
        }
256
257
        return null;
258
    }
259
260
    /**
261
     * @param array<int, array<string, mixed>> $productAbstractDataCollection
262
     *
263
     * @return list<int>
264
     */
265
    protected function extractProductAbstractIds(array $productAbstractDataCollection): array
266
    {
267
        $productAbstractIds = [];
268
        foreach ($productAbstractDataCollection as $productAbstractData) {
269
            $productAbstractIds[] = $productAbstractData[static::KEY_ID_PRODUCT_ABSTRACT];
270
        }
271
272
        return $productAbstractIds;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $productAbstractIds returns the type array|array<mixed,mixed> which is incompatible with the documented return type Spryker\Glue\ProductRevi...i\Processor\Reader\list.
Loading history...
273
    }
274
}
275