Passed
Push — master ( 321221...bff5d9 )
by Dmitry
03:28 queued 12s
created

PaymentForm::extendPyzPaymentCollection()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 14
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
/**
4
 * This file is part of the Spryker Commerce OS.
5
 * For full license information, please view the LICENSE file that was distributed with this source code.
6
 */
7
8
namespace Pyz\Yves\CheckoutPage\Form\Steps;
9
10
use Generated\Shared\Transfer\PaymentMethodsTransfer;
11
use Generated\Shared\Transfer\PaymentTransfer;
12
use Generated\Shared\Transfer\QuoteTransfer;
13
use Pyz\Yves\StepEngine\Dependency\Form\SubFormInterface as PyzSubFormInterface;
14
use Pyz\Yves\StepEngine\Dependency\Form\SubFormProviderNameInterface as PyzSubFormProviderNameInterface;
15
use Spryker\Yves\Kernel\Form\AbstractType;
16
use Spryker\Yves\StepEngine\Dependency\Form\SubFormProviderNameInterface as SprykerSubFormProviderNameInterface;
17
use Spryker\Yves\StepEngine\Dependency\Plugin\Form\SubFormPluginCollection;
18
use Spryker\Yves\StepEngine\Dependency\Plugin\Form\SubFormPluginInterface;
19
use SprykerShop\Yves\CheckoutPage\Form\StepEngine\ExtraOptionsSubFormInterface;
20
use SprykerShop\Yves\CheckoutPage\Form\StepEngine\StandaloneSubFormInterface;
21
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
22
use Symfony\Component\Form\FormBuilderInterface;
23
use Symfony\Component\Form\FormInterface;
24
use Symfony\Component\OptionsResolver\OptionsResolver;
25
use Symfony\Component\Validator\Constraint;
26
use Symfony\Component\Validator\Constraints\NotBlank;
27
28
/**
29
 * @method \SprykerShop\Yves\CheckoutPage\CheckoutPageFactory getFactory()
30
 * @method \Pyz\Yves\CheckoutPage\CheckoutPageConfig getConfig()
31
 */
32
class PaymentForm extends AbstractType
33
{
34
    /**
35
     * @var string
36
     */
37
    public const PYZ_PAYMENT_PROPERTY_PATH = QuoteTransfer::PAYMENT;
38
39
    /**
40
     * @var string
41
     */
42
    public const PYZ_PAYMENT_SELECTION = PaymentTransfer::PAYMENT_SELECTION;
43
44
    /**
45
     * @var string
46
     */
47
    public const PYZ_PAYMENT_SELECTION_PROPERTY_PATH = self::PYZ_PAYMENT_PROPERTY_PATH . '.' . self::PYZ_PAYMENT_SELECTION;
48
49
    /**
50
     * @var string
51
     */
52
    protected const PYZ_VALIDATION_NOT_BLANK_MESSAGE = 'validation.not_blank';
53
54
    /**
55
     * @return string
56
     */
57
    public function getBlockPrefix(): string
58
    {
59
        return 'paymentForm';
60
    }
61
62
    /**
63
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
64
     * @param array $options
65
     *
66
     * @return void
67
     */
68
    public function buildForm(FormBuilderInterface $builder, array $options): void
69
    {
70
        $this->addPyzPaymentMethods($builder, $options);
71
    }
72
73
    /**
74
     * @param \Symfony\Component\OptionsResolver\OptionsResolver $resolver
75
     *
76
     * @return void
77
     */
78
    public function configureOptions(OptionsResolver $resolver): void
79
    {
80
        $resolver->setDefaults([
81
            'validation_groups' => function (FormInterface $form) {
82
                $validationGroups = [Constraint::DEFAULT_GROUP];
83
84
                $paymentSelectionFormData = $form->get(self::PYZ_PAYMENT_SELECTION)->getData();
85
                if (is_string($paymentSelectionFormData)) {
86
                    $validationGroups[] = $paymentSelectionFormData;
87
                }
88
89
                return $validationGroups;
90
            },
91
            'attr' => [
92
                'novalidate' => 'novalidate',
93
            ],
94
        ]);
95
96
        $resolver->setRequired(PyzSubFormInterface::PYZ_OPTIONS_FIELD_NAME);
97
    }
98
99
    /**
100
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
101
     * @param array<\Spryker\Yves\StepEngine\Dependency\Form\SubFormInterface|\Pyz\Yves\StepEngine\Dependency\Form\SubFormInterface> $paymentMethodSubForms
102
     * @param array $options
103
     *
104
     * @return $this
105
     */
106
    protected function addPyzPaymentMethodSubForms(FormBuilderInterface $builder, array $paymentMethodSubForms, array $options)
107
    {
108
        foreach ($paymentMethodSubForms as $paymentMethodSubForm) {
109
            $paymentMethodSubFormOptions = $this->getPyzPaymentMethodSubFormOptions($paymentMethodSubForm);
110
111
            $builder->add(
112
                $this->getPyzSubFormName($paymentMethodSubForm),
113
                get_class($paymentMethodSubForm),
114
                ['select_options' => $options['select_options']] + $paymentMethodSubFormOptions,
115
            );
116
        }
117
118
        return $this;
119
    }
120
121
    /**
122
     * @param \Spryker\Yves\StepEngine\Dependency\Form\SubFormInterface|\Pyz\Yves\StepEngine\Dependency\Form\SubFormInterface $paymentMethodSubForm
123
     *
124
     * @return array<mixed>
125
     */
126
    protected function getPyzPaymentMethodSubFormOptions($paymentMethodSubForm): array
127
    {
128
        $defaultOptions = [
129
            'property_path' => static::PYZ_PAYMENT_PROPERTY_PATH . '.' . $this->getPyzSubFormPropertyPath($paymentMethodSubForm),
130
            'error_bubbling' => true,
131
            'label' => false,
132
        ];
133
134
        if (!$paymentMethodSubForm instanceof ExtraOptionsSubFormInterface) {
135
            return $defaultOptions;
136
        }
137
138
        return $defaultOptions + $paymentMethodSubForm->getExtraOptions();
0 ignored issues
show
Bug introduced by
The method getExtraOptions() does not exist on Pyz\Yves\StepEngine\Depe...y\Form\SubFormInterface. ( Ignorable by Annotation )

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

138
        return $defaultOptions + $paymentMethodSubForm->/** @scrutinizer ignore-call */ getExtraOptions();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
139
    }
140
141
    /**
142
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
143
     * @param array $options
144
     *
145
     * @return $this
146
     */
147
    protected function addPyzPaymentMethods(FormBuilderInterface $builder, array $options)
148
    {
149
        $paymentMethodSubForms = $this->getPyzPaymentMethodSubForms();
150
151
        $this->addPyzPaymentMethodChoices($builder, $paymentMethodSubForms)
152
            ->addPyzPaymentMethodSubForms($builder, $paymentMethodSubForms, $options);
153
154
        return $this;
155
    }
156
157
    /**
158
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
159
     * @param array<\Spryker\Yves\StepEngine\Dependency\Form\SubFormInterface|\Pyz\Yves\StepEngine\Dependency\Form\SubFormInterface> $paymentMethodSubForms
160
     *
161
     * @return $this
162
     */
163
    protected function addPyzPaymentMethodChoices(FormBuilderInterface $builder, array $paymentMethodSubForms)
164
    {
165
        $builder->add(
166
            static::PYZ_PAYMENT_SELECTION,
167
            ChoiceType::class,
168
            [
169
                'choices' => $this->getPyzPaymentMethodChoices($paymentMethodSubForms),
170
                'choice_name' => function ($choice, $key) use ($paymentMethodSubForms) {
171
                    $paymentMethodSubForm = $paymentMethodSubForms[$key];
172
173
                    return $this->getPyzSubFormName($paymentMethodSubForm);
174
                },
175
                'choice_label' => function ($choice, $key) use ($paymentMethodSubForms) {
176
                    $paymentMethodSubForm = $paymentMethodSubForms[$key];
177
178
                    if ($paymentMethodSubForm instanceof StandaloneSubFormInterface) {
179
                        return $paymentMethodSubForm->getLabelName();
0 ignored issues
show
Bug introduced by
The method getLabelName() does not exist on Pyz\Yves\StepEngine\Depe...y\Form\SubFormInterface. ( Ignorable by Annotation )

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

179
                        return $paymentMethodSubForm->/** @scrutinizer ignore-call */ getLabelName();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
180
                    }
181
182
                    return $this->getPyzSubFormName($paymentMethodSubForm);
183
                },
184
                'group_by' => function ($choice, $key) use ($paymentMethodSubForms) {
185
                    $paymentMethodSubForm = $paymentMethodSubForms[$key];
186
187
                    if ($paymentMethodSubForm instanceof StandaloneSubFormInterface) {
188
                        return $paymentMethodSubForm->getGroupName();
0 ignored issues
show
Bug introduced by
The method getGroupName() does not exist on Pyz\Yves\StepEngine\Depe...y\Form\SubFormInterface. ( Ignorable by Annotation )

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

188
                        return $paymentMethodSubForm->/** @scrutinizer ignore-call */ getGroupName();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
189
                    }
190
191
                    if ($paymentMethodSubForm instanceof SprykerSubFormProviderNameInterface) {
192
                        return sprintf('checkout.payment.provider.%s', $paymentMethodSubForm->getProviderName());
0 ignored issues
show
Bug introduced by
The method getProviderName() does not exist on Pyz\Yves\StepEngine\Depe...y\Form\SubFormInterface. ( Ignorable by Annotation )

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

192
                        return sprintf('checkout.payment.provider.%s', $paymentMethodSubForm->/** @scrutinizer ignore-call */ getProviderName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
193
                    }
194
195
                    if ($paymentMethodSubForm instanceof PyzSubFormProviderNameInterface) {
196
                        return sprintf('checkout.payment.provider.%s', $paymentMethodSubForm->getPyzProviderName());
197
                    }
198
199
                    return '';
200
                },
201
                'label' => false,
202
                'required' => true,
203
                'expanded' => true,
204
                'multiple' => false,
205
                'placeholder' => false,
206
                'property_path' => static::PYZ_PAYMENT_SELECTION_PROPERTY_PATH,
207
                'constraints' => [
208
                    $this->createPyzNotBlankConstraint(),
209
                ],
210
            ],
211
        );
212
213
        return $this;
214
    }
215
216
    /**
217
     * @return array<\Spryker\Yves\StepEngine\Dependency\Form\SubFormInterface|\Pyz\Yves\StepEngine\Dependency\Form\SubFormInterface>
218
     */
219
    protected function getPyzPaymentMethodSubForms(): array
220
    {
221
        $paymentMethodSubForms = [];
222
223
        $availablePaymentMethodsTransfer = $this->getFactory()->createPaymentMethodReader()
224
            ->getAvailablePaymentMethods();
225
226
        $availablePaymentMethodSubFormPlugins = $this->getFactory()->getPaymentMethodSubForms();
227
        $availablePaymentMethodSubFormPlugins = $this->filterPyzOutNotAvailableForms(
228
            $availablePaymentMethodSubFormPlugins,
229
            $availablePaymentMethodsTransfer,
230
        );
231
        $availablePaymentMethodSubFormPlugins = $this->extendPyzPaymentCollection(
232
            $availablePaymentMethodSubFormPlugins,
233
            $availablePaymentMethodsTransfer,
234
        );
235
        $filteredPaymentMethodSubFormPlugins = $this->filterPyzPaymentMethodSubFormPlugins($availablePaymentMethodSubFormPlugins);
236
237
        foreach ($filteredPaymentMethodSubFormPlugins as $paymentMethodSubFormPlugin) {
238
            $paymentMethodSubForm = $this->createPyzSubForm($paymentMethodSubFormPlugin);
239
            $paymentMethodSubForms[$this->getPyzSubFormName($paymentMethodSubForm)] = $paymentMethodSubForm;
240
        }
241
242
        return $paymentMethodSubForms;
243
    }
244
245
    /**
246
     * @param \Spryker\Yves\StepEngine\Dependency\Plugin\Form\SubFormPluginCollection $paymentSubFormPluginCollection
247
     * @param \Generated\Shared\Transfer\PaymentMethodsTransfer $paymentMethodsTransfer
248
     *
249
     * @return \Spryker\Yves\StepEngine\Dependency\Plugin\Form\SubFormPluginCollection
250
     */
251
    protected function extendPyzPaymentCollection(
252
        SubFormPluginCollection $paymentSubFormPluginCollection,
253
        PaymentMethodsTransfer $paymentMethodsTransfer
254
    ): SubFormPluginCollection {
255
        $paymentCollectionExtenderPlugins = $this->getFactory()->getPaymentCollectionExtenderPlugins();
256
257
        foreach ($paymentCollectionExtenderPlugins as $paymentCollectionExtenderPlugin) {
258
            $paymentSubFormPluginCollection = $paymentCollectionExtenderPlugin->extendCollection(
259
                $paymentSubFormPluginCollection,
260
                $paymentMethodsTransfer,
261
            );
262
        }
263
264
        return $paymentSubFormPluginCollection;
265
    }
266
267
    /**
268
     * @param \Spryker\Yves\StepEngine\Dependency\Plugin\Form\SubFormPluginCollection $paymentMethodSubFormPlugins
269
     * @param \Generated\Shared\Transfer\PaymentMethodsTransfer $availablePaymentMethodsTransfer
270
     *
271
     * @return \Spryker\Yves\StepEngine\Dependency\Plugin\Form\SubFormPluginCollection
272
     */
273
    protected function filterPyzOutNotAvailableForms(
274
        SubFormPluginCollection $paymentMethodSubFormPlugins,
275
        PaymentMethodsTransfer $availablePaymentMethodsTransfer
276
    ): SubFormPluginCollection {
277
        $paymentMethodNames = $this->getPyzAvailablePaymentMethodNames($availablePaymentMethodsTransfer);
278
        $paymentMethodNames = array_combine($paymentMethodNames, $paymentMethodNames);
279
280
        foreach ($paymentMethodSubFormPlugins as $key => $subFormPlugin) {
281
            $subFormName = $this->getPyzSubFormName($subFormPlugin->createSubForm());
282
283
            if (!isset($paymentMethodNames[$subFormName])) {
284
                unset($paymentMethodSubFormPlugins[$key]);
285
            }
286
        }
287
288
        $paymentMethodSubFormPlugins->reset();
289
290
        return $paymentMethodSubFormPlugins;
291
    }
292
293
    /**
294
     * @param \Generated\Shared\Transfer\PaymentMethodsTransfer $availablePaymentMethodsTransfer
295
     *
296
     * @return array<string>
297
     */
298
    protected function getPyzAvailablePaymentMethodNames(PaymentMethodsTransfer $availablePaymentMethodsTransfer): array
299
    {
300
        $paymentMethodNames = [];
301
        foreach ($availablePaymentMethodsTransfer->getMethods() as $paymentMethodTransfer) {
302
            $paymentMethodNames[] = $paymentMethodTransfer->getMethodName();
303
        }
304
305
        return $paymentMethodNames;
306
    }
307
308
    /**
309
     * @param array<\Spryker\Yves\StepEngine\Dependency\Form\SubFormInterface|\Pyz\Yves\StepEngine\Dependency\Form\SubFormInterface> $paymentMethodSubForms
310
     *
311
     * @return array<string, string>
312
     */
313
    protected function getPyzPaymentMethodChoices(array $paymentMethodSubForms): array
314
    {
315
        $choices = [];
316
317
        foreach ($paymentMethodSubForms as $paymentMethodSubForm) {
318
            $choices[$this->getPyzSubFormName($paymentMethodSubForm)] = $this->getPyzSubFormPropertyPath($paymentMethodSubForm);
319
        }
320
321
        return $choices;
322
    }
323
324
    /**
325
     * @param \Spryker\Yves\StepEngine\Dependency\Plugin\Form\SubFormPluginCollection $availablePaymentMethodSubFormPlugins
326
     *
327
     * @return \Spryker\Yves\StepEngine\Dependency\Plugin\Form\SubFormPluginCollection
328
     */
329
    protected function filterPyzPaymentMethodSubFormPlugins(SubFormPluginCollection $availablePaymentMethodSubFormPlugins): SubFormPluginCollection
330
    {
331
        return $this->getFactory()
332
            ->createSubFormFilter()
333
            ->filterFormsCollection($availablePaymentMethodSubFormPlugins);
334
    }
335
336
    /**
337
     * @return \Symfony\Component\Validator\Constraints\NotBlank
338
     */
339
    protected function createPyzNotBlankConstraint(): NotBlank
340
    {
341
        return new NotBlank(['message' => static::PYZ_VALIDATION_NOT_BLANK_MESSAGE]);
342
    }
343
344
    /**
345
     * @param \Spryker\Yves\StepEngine\Dependency\Plugin\Form\SubFormPluginInterface $paymentMethodSubForm
346
     *
347
     * @return \Spryker\Yves\StepEngine\Dependency\Form\SubFormInterface|\Pyz\Yves\StepEngine\Dependency\Form\SubFormInterface
348
     */
349
    protected function createPyzSubForm(SubFormPluginInterface $paymentMethodSubForm)
350
    {
351
        /** @var \Spryker\Yves\StepEngine\Dependency\Form\SubFormInterface|\Pyz\Yves\StepEngine\Dependency\Form\SubFormInterface $paymentSubForm */
352
        $paymentSubForm = $paymentMethodSubForm->createSubForm();
353
354
        return $paymentSubForm;
355
    }
356
357
    /**
358
     * @param \Spryker\Yves\StepEngine\Dependency\Form\SubFormInterface|\Pyz\Yves\StepEngine\Dependency\Form\SubFormInterface $paymentSubForm
359
     *
360
     * @return string
361
     */
362
    protected function getPyzSubFormName($paymentSubForm): string
363
    {
364
        if ($paymentSubForm instanceof PyzSubFormInterface) {
365
            return $paymentSubForm->getPyzName();
366
        }
367
368
        return $paymentSubForm->getName();
369
    }
370
371
    /**
372
     * @param \Spryker\Yves\StepEngine\Dependency\Form\SubFormInterface|\Pyz\Yves\StepEngine\Dependency\Form\SubFormInterface $paymentSubForm
373
     *
374
     * @return string
375
     */
376
    protected function getPyzSubFormPropertyPath($paymentSubForm): string
377
    {
378
        if ($paymentSubForm instanceof PyzSubFormInterface) {
379
            return $paymentSubForm->getPyzPropertyPath();
380
        }
381
382
        return $paymentSubForm->getPropertyPath();
383
    }
384
}
385