Completed
Push — master ( fb754a...2a3626 )
by Antonio
03:49
created

ProductController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 29
rs 9.8333
c 0
b 0
f 0
cc 1
nc 1
nop 13

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Flagbit\Bundle\ProductClonerBundle\Controller;
4
5
use Akeneo\Component\StorageUtils\Saver\SaverInterface;
6
use Akeneo\Component\StorageUtils\Updater\ObjectUpdaterInterface;
7
use Oro\Bundle\SecurityBundle\Annotation\AclAncestor;
8
use Pim\Bundle\UserBundle\Context\UserContext;
9
use Pim\Component\Catalog\Builder\ProductBuilderInterface;
10
use Pim\Component\Catalog\Comparator\Filter\FilterInterface;
11
use Pim\Component\Catalog\Localization\Localizer\AttributeConverterInterface;
12
use Pim\Component\Catalog\Model\ProductInterface;
13
use Pim\Component\Catalog\Repository\AttributeRepositoryInterface;
14
use Pim\Component\Catalog\Repository\ProductRepositoryInterface;
15
use Pim\Component\Enrich\Converter\ConverterInterface;
16
use Symfony\Component\HttpFoundation\JsonResponse;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
20
use Symfony\Component\Validator\Validator\ValidatorInterface;
21
22
class ProductController extends AbstractController
23
{
24
    /**
25
     * @var ProductRepositoryInterface
26
     */
27
    private $productRepository;
28
    /**
29
     * @var ObjectUpdaterInterface
30
     */
31
    private $productUpdater;
32
    /**
33
     * @var SaverInterface
34
     */
35
    private $productSaver;
36
    /**
37
     * @var NormalizerInterface
38
     */
39
    private $normalizer;
40
    /**
41
     * @var ValidatorInterface
42
     */
43
    private $validator;
44
    /**
45
     * @var UserContext
46
     */
47
    private $userContext;
48
    /**
49
     * @var ProductBuilderInterface
50
     */
51
    private $productBuilder;
52
    /**
53
     * @var AttributeConverterInterface
54
     */
55
    private $localizedConverter;
56
    /**
57
     * @var FilterInterface
58
     */
59
    private $emptyValuesFilter;
60
    /**
61
     * @var ConverterInterface
62
     */
63
    private $productValueConverter;
64
    /**
65
     * @var NormalizerInterface
66
     */
67
    private $constraintViolationNormalizer;
68
    /**
69
     * @var ProductBuilderInterface
70
     */
71
    private $variantProductBuilder;
72
    /**
73
     * @var AttributeRepositoryInterface
74
     */
75
    private $attributeRepository;
76
77
    public function __construct(
78
        ProductRepositoryInterface $productRepository,
79
        AttributeRepositoryInterface $attributeRepository,
80
        ObjectUpdaterInterface $productUpdater,
81
        SaverInterface $productSaver,
82
        NormalizerInterface $normalizer,
83
        ValidatorInterface $validator,
84
        UserContext $userContext,
85
        ProductBuilderInterface $productBuilder,
86
        AttributeConverterInterface $localizedConverter,
87
        FilterInterface $emptyValuesFilter,
88
        ConverterInterface $productValueConverter,
89
        NormalizerInterface $constraintViolationNormalizer,
90
        ProductBuilderInterface $variantProductBuilder
91
    ) {
92
93
        $this->productRepository = $productRepository;
94
        $this->productUpdater = $productUpdater;
95
        $this->productSaver = $productSaver;
96
        $this->normalizer = $normalizer;
97
        $this->validator = $validator;
98
        $this->userContext = $userContext;
99
        $this->productBuilder = $productBuilder;
100
        $this->localizedConverter = $localizedConverter;
101
        $this->emptyValuesFilter = $emptyValuesFilter;
102
        $this->productValueConverter = $productValueConverter;
103
        $this->constraintViolationNormalizer = $constraintViolationNormalizer;
104
        $this->variantProductBuilder = $variantProductBuilder;
105
        $this->attributeRepository = $attributeRepository;
106
    }
107
    /**
108
     * @param Request $request
109
     *
110
     * @AclAncestor("pim_enrich_product_model_create")
111
     *
112
     * @return JsonResponse
113
     */
114
    public function cloneAction(Request $request) : JsonResponse
115
    {
116
        $data = json_decode($request->getContent(), true);
117
118
        // check 'code_to_clone' is provided otherwise HTTP bad request
119
        if (false === isset($data['code_to_clone'])) {
120
            return new JsonResponse('Field "code_to_clone" is missing.', Response::HTTP_BAD_REQUEST);
121
        }
122
123
        // check whether product to be cloned is found otherwise not found HTTP
124
        $product = $this->productRepository->findOneByIdentifier($data['code_to_clone']);
125
        if (null === $product) {
126
            return new JsonResponse(
127
                sprintf('Product model with code %s could not be found.', $data['code_to_clone']),
128
                Response::HTTP_NOT_FOUND
129
            );
130
        }
131
        unset($data['code_to_clone']);
132
        if (isset($data['parent'])) {
133
            // TODO: remove this as soon as support of 2.1 is dropped
134
            $cloneProduct = $this->variantProductBuilder->createProduct();
135
        } else {
136
            $cloneProduct = $this->productBuilder->createProduct(
137
                $data['code']
138
            );
139
            unset($data['code']);
140
        }
141
142
        // clone product using Akeneo normalizer
143
        $normalizedProduct = $this->normalizeProduct($product);
144
145
        $normalizedProduct = $this->removeIdentifierAttributeValue($normalizedProduct);
0 ignored issues
show
Bug introduced by
It seems like $normalizedProduct can also be of type boolean and double and integer and string; however, parameter $data of Flagbit\Bundle\ProductCl...ntifierAttributeValue() does only seem to accept array, 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

145
        $normalizedProduct = $this->removeIdentifierAttributeValue(/** @scrutinizer ignore-type */ $normalizedProduct);
Loading history...
146
        $this->productUpdater->update($cloneProduct, $normalizedProduct);
147
        if (!empty($data['values'])) {
148
            $this->updateProduct($cloneProduct, $data);
149
        }
150
        // validate product model clone and return violations if found
151
        $violations = $this->validator->validate($cloneProduct);
152
        if (count($violations) > 0) {
153
            $normalizedViolations = [];
154
            foreach ($violations as $violation) {
155
                $violation = $this->constraintViolationNormalizer->normalize(
156
                    $violation,
157
                    'internal_api',
158
                    ['product' => $cloneProduct]
159
                );
160
                $normalizedViolations[] = $violation;
161
            }
162
163
            return new JsonResponse(['values' => $normalizedViolations], Response::HTTP_BAD_REQUEST);
164
        }
165
166
        $this->productSaver->save($cloneProduct);
167
168
        return new JsonResponse();
169
    }
170
171
    private function removeIdentifierAttributeValue(array $data): array
172
    {
173
        unset($data['identifier']);
174
        $identifierAttributeCode = $this->attributeRepository->getIdentifier()->getCode();
175
176
        if (isset($data['values'][$identifierAttributeCode])) {
177
            unset($data['values'][$identifierAttributeCode]);
178
        }
179
        return $data;
180
    }
181
    /**
182
     * Updates product with the provided request data
183
     *
184
     * @param ProductInterface $product
185
     * @param array            $data
186
     */
187
    private function updateProduct(ProductInterface $product, array $data)
188
    {
189
        $values = $this->productValueConverter->convert($data['values']);
190
191
        $values = $this->localizedConverter->convertToDefaultFormats($values, [
192
            'locale' => $this->userContext->getUiLocale()->getCode()
193
        ]);
194
195
        $dataFiltered = $this->emptyValuesFilter->filter($product, ['values' => $values]);
196
197
        if (!empty($dataFiltered)) {
198
            $data = array_replace($data, $dataFiltered);
199
        } else {
200
            $data['values'] = [];
201
        }
202
203
        $this->productUpdater->update($product, $data);
204
    }
205
206
    protected function getNormalizer(): NormalizerInterface
207
    {
208
        return $this->normalizer;
209
    }
210
211
    protected function getAttributeRepository(): AttributeRepositoryInterface
212
    {
213
        return $this->attributeRepository;
214
    }
215
}
216