Failed Conditions
Push — master ( 999028...ace778 )
by
unknown
37:54
created

SspAssetForm   D

Complexity

Total Complexity 59

Size/Duplication

Total Lines 630
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 262
c 0
b 0
f 0
dl 0
loc 630
rs 4.08
wmc 59

17 Methods

Rating   Name   Duplication   Size   Complexity  
A addNameField() 0 17 1
A addNoteField() 0 16 1
C addCompanyAssignmentValidationListener() 0 60 12
A extractBusinessUnitsFromTransfer() 0 16 4
A addImageField() 0 8 1
A addStatusField() 0 10 1
A addAssignedBusinessUnitDataListener() 0 16 4
A extractCompaniesFromTransfer() 0 16 4
C addBusinessUnitAssignmentValidationListener() 0 73 16
A addBusinessUnitOwnerField() 0 40 3
A configureOptions() 0 16 1
A addSerialNumberField() 0 15 1
A getBlockPrefix() 0 3 1
A addAssignedBusinessUnitField() 0 19 1
A buildForm() 0 16 1
A addCompanyField() 0 20 1
A addBusinessUnitOwnerValidationListener() 0 23 6

How to fix   Complexity   

Complex Class

Complex classes like SspAssetForm often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SspAssetForm, and based on these observations, apply Extract Interface, too.

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 SprykerFeature\Zed\SelfServicePortal\Communication\Asset\Form;
9
10
use Generated\Shared\Transfer\CompanyBusinessUnitCriteriaFilterTransfer;
11
use Generated\Shared\Transfer\CompanyBusinessUnitTransfer;
12
use Generated\Shared\Transfer\CompanyCriteriaFilterTransfer;
13
use Generated\Shared\Transfer\SspAssetTransfer;
14
use Spryker\Zed\Gui\Communication\Form\Type\Select2ComboBoxType;
15
use Spryker\Zed\Kernel\Communication\Form\AbstractType;
16
use Symfony\Component\Form\CallbackTransformer;
17
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
18
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
19
use Symfony\Component\Form\Extension\Core\Type\TextType;
20
use Symfony\Component\Form\FormBuilderInterface;
21
use Symfony\Component\Form\FormError;
22
use Symfony\Component\Form\FormEvent;
23
use Symfony\Component\Form\FormEvents;
24
use Symfony\Component\OptionsResolver\OptionsResolver;
25
use Symfony\Component\Validator\Constraints\Length;
26
use Symfony\Component\Validator\Constraints\NotBlank;
27
28
/**
29
 * @method \SprykerFeature\Zed\SelfServicePortal\Communication\SelfServicePortalCommunicationFactory getFactory()
30
 * @method \SprykerFeature\Zed\SelfServicePortal\SelfServicePortalConfig getConfig()
31
 * @method \SprykerFeature\Zed\SelfServicePortal\Business\SelfServicePortalFacadeInterface getFacade()
32
 * @method \SprykerFeature\Zed\SelfServicePortal\Persistence\SelfServicePortalRepositoryInterface getRepository()
33
 */
34
class SspAssetForm extends AbstractType
35
{
36
    /**
37
     * @var string
38
     */
39
    protected const FIELD_NAME = 'name';
40
41
    /**
42
     * @var string
43
     */
44
    public const FIELD_BUSINESS_UNIT_OWNER = 'companyBusinessUnit';
45
46
    /**
47
     * @var string
48
     */
49
    protected const FIELD_SERIAL_NUMBER = 'serialNumber';
50
51
    /**
52
     * @var string
53
     */
54
    protected const FIELD_STATUS = 'status';
55
56
    /**
57
     * @var string
58
     */
59
    protected const FIELD_NOTE = 'note';
60
61
    /**
62
     * @var string
63
     */
64
    public const FIELD_ASSIGNED_COMPANIES = 'assignedCompanies';
65
66
    /**
67
     * @var string
68
     */
69
    protected const LABEL_COMPANY = 'Company';
70
71
    /**
72
     * @var string
73
     */
74
    protected const LABEL_BUSINESS_UNIT_OWNER = 'Business unit owner';
75
76
    /**
77
     * @var string
78
     */
79
    public const FIELD_IMAGE = 'asset_image';
80
81
    /**
82
     * @var string
83
     */
84
    public const OPTION_ORIGINAL_IMAGE_URL = 'imageUrl';
85
86
    /**
87
     * @var string
88
     */
89
    public const FIELD_ASSIGNED_BUSINESS_UNITS = 'assignedBusinessUnits';
90
91
    /**
92
     * @var string
93
     */
94
    protected const LABEL_BUSINESS_UNIT = 'Business Units';
95
96
    /**
97
     * @uses \Spryker\Zed\CompanyGui\Communication\Controller\SuggestController::indexAction()
98
     *
99
     * @var string
100
     */
101
    protected const ROUTE_COMPANY_SUGGEST = '/company-gui/suggest';
102
103
    /**
104
     * @uses \Spryker\Zed\CompanyBusinessUnitGui\Communication\Controller\SuggestController::indexAction()
105
     *
106
     * @var string
107
     */
108
    protected const ROUTE_BUSINESS_UNIT_SUGGEST = '/company-business-unit-gui/suggest?';
109
110
    /**
111
     * @var string
112
     */
113
    protected const PLACEHOLDER_SEARCH = 'Start typing to search...';
114
115
    /**
116
     * @var string
117
     */
118
    public const OPTION_COMPANY_ASSIGMENT_OPTIONS = 'companyAssignments';
119
120
    /**
121
     * @var string
122
     */
123
    public const OPTION_BUSINESS_UNIT_ASSIGMENT_OPTIONS = 'businessUnitAssignments';
124
125
    /**
126
     * @var string
127
     */
128
    public const OPTION_BUSINESS_UNIT_OWNER = 'businessUnitOwner';
129
130
    /**
131
     * @var string
132
     */
133
    public const OPTION_STATUS_OPTIONS = 'statuses';
134
135
    /**
136
     * @var string
137
     */
138
    public const FORM_NAME = 'assetForm';
139
140
    /**
141
     * @return string
142
     */
143
    public function getBlockPrefix(): string
144
    {
145
        return static::FORM_NAME;
146
    }
147
148
    /**
149
     * @param \Symfony\Component\OptionsResolver\OptionsResolver $resolver
150
     *
151
     * @return void
152
     */
153
    public function configureOptions(OptionsResolver $resolver): void
154
    {
155
        $resolver->setRequired([
156
            static::OPTION_BUSINESS_UNIT_ASSIGMENT_OPTIONS,
157
            static::OPTION_BUSINESS_UNIT_OWNER,
158
            static::OPTION_STATUS_OPTIONS,
159
            static::OPTION_COMPANY_ASSIGMENT_OPTIONS,
160
            ]);
161
162
        $resolver->setDefaults([
163
            'data_class' => SspAssetTransfer::class,
164
            static::OPTION_ORIGINAL_IMAGE_URL => null,
165
            static::OPTION_BUSINESS_UNIT_ASSIGMENT_OPTIONS => [],
166
            static::OPTION_COMPANY_ASSIGMENT_OPTIONS => [],
167
            static::OPTION_STATUS_OPTIONS => [],
168
            static::OPTION_BUSINESS_UNIT_OWNER => [],
169
        ]);
170
    }
171
172
    /**
173
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
174
     * @param array<string, mixed> $options
175
     *
176
     * @return void
177
     */
178
    public function buildForm(FormBuilderInterface $builder, array $options): void
179
    {
180
        $this
181
            ->addImageField($builder, $options)
182
            ->addNameField($builder)
183
            ->addSerialNumberField($builder)
184
            ->addStatusField($builder, $options)
185
            ->addNoteField($builder)
186
            ->addCompanyField($builder, $options)
187
            ->addAssignedBusinessUnitField($builder, $options)
188
            ->addBusinessUnitOwnerField($builder, $options);
189
190
        $this->addAssignedBusinessUnitDataListener($builder);
191
        $this->addBusinessUnitOwnerValidationListener($builder);
192
        $this->addCompanyAssignmentValidationListener($builder);
193
        $this->addBusinessUnitAssignmentValidationListener($builder);
194
    }
195
196
    /**
197
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
198
     * @param array<string, mixed> $options
199
     *
200
     * @return $this
201
     */
202
    protected function addBusinessUnitOwnerField(FormBuilderInterface $builder, array $options = [])
203
    {
204
        $builder->add(static::FIELD_BUSINESS_UNIT_OWNER, Select2ComboBoxType::class, [
205
            'label' => static::LABEL_BUSINESS_UNIT_OWNER,
206
            'choices' => $options[static::OPTION_BUSINESS_UNIT_OWNER],
207
            'multiple' => false,
208
            'mapped' => true,
209
            'required' => false,
210
            'attr' => [
211
                'data-autocomplete-url' => static::ROUTE_BUSINESS_UNIT_SUGGEST,
212
                'data-clear-initial' => false,
213
                'dependent-autocomplete-key' => 'idsCompany',
214
                'data-depends-on-field' => '.js-select-dependable--assigned-companies',
215
                'class' => 'js-select-dependable js-select-dependable--business-unit spryker-form-select2combobox',
216
                'data-minimum-input-length' => 4,
217
                'placeholder' => static::PLACEHOLDER_SEARCH,
218
                'data-clearable' => true,
219
            ],
220
        ]);
221
222
        $builder->get(static::FIELD_BUSINESS_UNIT_OWNER)->addModelTransformer(
223
            new CallbackTransformer(
224
                function ($companyBusinessUnitTransfer) {
225
                    if (!$companyBusinessUnitTransfer instanceof CompanyBusinessUnitTransfer) {
226
                        return null;
227
                    }
228
229
                    return $companyBusinessUnitTransfer->getIdCompanyBusinessUnit();
230
                },
231
                function ($idCompanyBusinessUnitSubmitted) {
232
                    if (!$idCompanyBusinessUnitSubmitted) {
233
                        return null;
234
                    }
235
236
                    return (new CompanyBusinessUnitTransfer())->setIdCompanyBusinessUnit($idCompanyBusinessUnitSubmitted);
237
                },
238
            ),
239
        );
240
241
        return $this;
242
    }
243
244
    /**
245
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
246
     *
247
     * @return $this
248
     */
249
    protected function addNameField(FormBuilderInterface $builder)
250
    {
251
        $builder->add(static::FIELD_NAME, TextType::class, [
252
            'label' => 'Name',
253
            'required' => true,
254
            'sanitize_xss' => true,
255
            'constraints' => [
256
                new NotBlank(),
257
                new Length([
258
                    'min' => 3,
259
                    'max' => 255,
260
                    'minMessage' => 'self_service_portal.asset.form.name.validation.min',
261
                ]),
262
            ],
263
        ]);
264
265
        return $this;
266
    }
267
268
    /**
269
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
270
     *
271
     * @return $this
272
     */
273
    protected function addSerialNumberField(FormBuilderInterface $builder)
274
    {
275
        $builder->add(static::FIELD_SERIAL_NUMBER, TextType::class, [
276
            'label' => 'Serial number',
277
            'required' => false,
278
            'sanitize_xss' => true,
279
            'constraints' => [
280
                new Length([
281
                    'max' => 255,
282
                    'minMessage' => 'self_service_portal.asset.form.serial_number.validation.min',
283
                ]),
284
            ],
285
        ]);
286
287
        return $this;
288
    }
289
290
    /**
291
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
292
     * @param array<string, mixed> $options
293
     *
294
     * @return $this
295
     */
296
    protected function addStatusField(FormBuilderInterface $builder, array $options = [])
297
    {
298
        $builder->add(static::FIELD_STATUS, ChoiceType::class, [
299
            'label' => 'Status',
300
            'required' => true,
301
            'choices' => $options[static::OPTION_STATUS_OPTIONS],
302
            'multiple' => false,
303
        ]);
304
305
        return $this;
306
    }
307
308
    /**
309
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
310
     *
311
     * @return $this
312
     */
313
    protected function addNoteField(FormBuilderInterface $builder)
314
    {
315
        $builder->add(static::FIELD_NOTE, TextareaType::class, [
316
            'label' => 'Note',
317
            'required' => false,
318
            'sanitize_xss' => true,
319
            'constraints' => [
320
                new Length([
321
                    'max' => 1000,
322
                    'minMessage' => 'self_service_portal.asset.form.note.validation.min',
323
                ]),
324
            ],
325
            'attr' => ['rows' => 5],
326
        ]);
327
328
        return $this;
329
    }
330
331
    /**
332
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
333
     * @param array<string, mixed> $options
334
     *
335
     * @return $this
336
     */
337
    protected function addImageField(FormBuilderInterface $builder, array $options = [])
338
    {
339
        $builder->add(static::FIELD_IMAGE, SspAssetImageForm::class, [
340
            'mapped' => false,
341
            SspAssetImageForm::OPTION_ORIGINAL_IMAGE_URL => $options[static::OPTION_ORIGINAL_IMAGE_URL] ?? null,
342
        ]);
343
344
        return $this;
345
    }
346
347
    /**
348
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
349
     * @param array<string, mixed> $options
350
     *
351
     * @return $this
352
     */
353
    protected function addCompanyField(FormBuilderInterface $builder, array $options = [])
354
    {
355
        $builder->add(static::FIELD_ASSIGNED_COMPANIES, Select2ComboBoxType::class, [
356
            'label' => static::LABEL_COMPANY,
357
            'choices' => $options[static::OPTION_COMPANY_ASSIGMENT_OPTIONS],
358
            'multiple' => true,
359
            'mapped' => false,
360
            'required' => false,
361
            'attr' => [
362
                'data-autocomplete-url' => static::ROUTE_COMPANY_SUGGEST,
363
                'data-minimum-input-length' => 4,
364
                'dependent-autocomplete-key' => 'idsCompany',
365
                'data-dependent-name' => 'idsCompany',
366
                'placeholder' => static::PLACEHOLDER_SEARCH,
367
                'data-qa' => 'ssp-asset-assigned-companies-field',
368
                'class' => 'js-select-dependable--assigned-companies',
369
            ],
370
        ]);
371
372
        return $this;
373
    }
374
375
    /**
376
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
377
     * @param array<string, mixed> $options
378
     *
379
     * @return $this
380
     */
381
    protected function addAssignedBusinessUnitField(FormBuilderInterface $builder, array $options = [])
382
    {
383
        $builder->add(static::FIELD_ASSIGNED_BUSINESS_UNITS, Select2ComboBoxType::class, [
384
            'label' => static::LABEL_BUSINESS_UNIT,
385
            'choices' => $options[static::OPTION_BUSINESS_UNIT_ASSIGMENT_OPTIONS],
386
            'multiple' => true,
387
            'required' => false,
388
            'mapped' => false,
389
            'attr' => [
390
                'data-autocomplete-url' => static::ROUTE_BUSINESS_UNIT_SUGGEST,
391
                'data-clear-initial' => false,
392
                'dependent-autocomplete-key' => 'idsCompany',
393
                'data-depends-on-field' => '.js-select-dependable--assigned-companies',
394
                'class' => 'js-select-dependable js-select-dependable--business-unit spryker-form-select2combobox',
395
                'data-qa' => 'ssp-asset-business-unit-field',
396
            ],
397
        ]);
398
399
        return $this;
400
    }
401
402
    /**
403
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
404
     *
405
     * @return void
406
     */
407
    protected function addAssignedBusinessUnitDataListener(FormBuilderInterface $builder): void
408
    {
409
        $builder->addEventListener(
410
            FormEvents::POST_SET_DATA,
411
            function (FormEvent $event): void {
412
                $sspAssetTransfer = $event->getData();
413
414
                if (!$sspAssetTransfer instanceof SspAssetTransfer) {
415
                    return;
416
                }
417
418
                if ($event->getForm()->has(static::FIELD_ASSIGNED_BUSINESS_UNITS)) {
419
                    $event->getForm()->get(static::FIELD_ASSIGNED_BUSINESS_UNITS)->setData($this->extractBusinessUnitsFromTransfer($sspAssetTransfer));
420
                }
421
                if ($event->getForm()->has(static::FIELD_ASSIGNED_COMPANIES)) {
422
                    $event->getForm()->get(static::FIELD_ASSIGNED_COMPANIES)->setData($this->extractCompaniesFromTransfer($sspAssetTransfer));
423
                }
424
            },
425
        );
426
    }
427
428
    /**
429
     * Adds a validation listener to ensure business unit owner is one of the assigned business units
430
     *
431
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
432
     *
433
     * @return void
434
     */
435
    protected function addBusinessUnitOwnerValidationListener(FormBuilderInterface $builder): void
436
    {
437
        $builder->addEventListener(
438
            FormEvents::PRE_SUBMIT,
439
            function (FormEvent $event): void {
440
                $data = $event->getData();
441
                $form = $event->getForm();
442
443
                $businessUnitOwnerId = $data[static::FIELD_BUSINESS_UNIT_OWNER] ?? null;
444
                $assignedBusinessUnitIds = $data[static::FIELD_ASSIGNED_BUSINESS_UNITS] ?? [];
445
446
                if (!$businessUnitOwnerId && $assignedBusinessUnitIds === []) {
447
                    return;
448
                }
449
450
                if (!$businessUnitOwnerId && $assignedBusinessUnitIds !== []) {
451
                    $form->addError(new FormError('Business unit owner is required when business units are assigned.'));
452
453
                    return;
454
                }
455
456
                if (!in_array($businessUnitOwnerId, $assignedBusinessUnitIds)) {
457
                    $form->addError(new FormError('Business unit owner must be one of the assigned business units.'));
458
                }
459
            },
460
        );
461
    }
462
463
    /**
464
     * Adds a validation listener to ensure assigned companies contain all companies from assigned business units
465
     *
466
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
467
     *
468
     * @return void
469
     */
470
    protected function addCompanyAssignmentValidationListener(FormBuilderInterface $builder): void
471
    {
472
        $builder->addEventListener(
473
            FormEvents::PRE_SUBMIT,
474
            function (FormEvent $event): void {
475
                $data = $event->getData();
476
                $form = $event->getForm();
477
478
                if (!isset($data[static::FIELD_ASSIGNED_BUSINESS_UNITS]) || !$data[static::FIELD_ASSIGNED_BUSINESS_UNITS]) {
479
                    return;
480
                }
481
482
                if (!isset($data[static::FIELD_ASSIGNED_COMPANIES]) || !$data[static::FIELD_ASSIGNED_COMPANIES]) {
483
                    $form->addError(new FormError('Companies must be assigned when business units are assigned.'));
484
485
                    return;
486
                }
487
488
                $assignedBusinessUnitIds = array_map('intval', $data[static::FIELD_ASSIGNED_BUSINESS_UNITS]);
489
                $assignedCompanyIds = array_map('intval', $data[static::FIELD_ASSIGNED_COMPANIES]);
490
491
                $businessUnitOptions = $form->getConfig()->getOption(static::OPTION_BUSINESS_UNIT_ASSIGMENT_OPTIONS);
492
                $companyOptions = $form->getConfig()->getOption(static::OPTION_COMPANY_ASSIGMENT_OPTIONS);
493
494
                if (!$businessUnitOptions || !$companyOptions) {
495
                    return;
496
                }
497
498
                $companyBusinessUnitFacade = $this->getFactory()->getCompanyBusinessUnitFacade();
499
                $businessUnitCollection = $companyBusinessUnitFacade->getCompanyBusinessUnitCollection(
500
                    (new CompanyBusinessUnitCriteriaFilterTransfer())->setCompanyBusinessUnitIds($assignedBusinessUnitIds),
501
                );
502
503
                $requiredCompanyIds = [];
504
                foreach ($businessUnitCollection->getCompanyBusinessUnits() as $businessUnit) {
505
                    if ($businessUnit->getCompany() && $businessUnit->getCompany()->getIdCompany()) {
506
                        $requiredCompanyIds[] = $businessUnit->getCompany()->getIdCompany();
507
                    }
508
                }
509
510
                $requiredCompanyIds = array_unique($requiredCompanyIds);
511
                $missingCompanyIds = array_diff($requiredCompanyIds, $assignedCompanyIds);
512
513
                if ($missingCompanyIds) {
514
                    $companyFacade = $this->getFactory()->getCompanyFacade();
515
                    $missingCompanyCollection = $companyFacade->getCompanyCollection(
516
                        (new CompanyCriteriaFilterTransfer())->setCompanyIds($missingCompanyIds),
517
                    );
518
519
                    $missingCompanyNames = [];
520
                    foreach ($missingCompanyCollection->getCompanies() as $company) {
521
                        $missingCompanyNames[] = $company->getName();
522
                    }
523
524
                    $errorMessage = sprintf(
525
                        'All companies that own the assigned business units must be included in assigned companies. Missing companies: %s.',
526
                        implode(', ', $missingCompanyNames),
527
                    );
528
529
                    $form->addError(new FormError($errorMessage));
530
                }
531
            },
532
        );
533
    }
534
535
    /**
536
     * Adds a validation listener to ensure that if a company is selected, at least one business unit of that company is selected too
537
     *
538
     * @param \Symfony\Component\Form\FormBuilderInterface $builder
539
     *
540
     * @return void
541
     */
542
    protected function addBusinessUnitAssignmentValidationListener(FormBuilderInterface $builder): void
543
    {
544
        $builder->addEventListener(
545
            FormEvents::PRE_SUBMIT,
546
            function (FormEvent $event): void {
547
                $data = $event->getData();
548
                $form = $event->getForm();
549
550
                if (!isset($data[static::FIELD_ASSIGNED_COMPANIES]) || !$data[static::FIELD_ASSIGNED_COMPANIES]) {
551
                    return;
552
                }
553
554
                if (!isset($data[static::FIELD_ASSIGNED_BUSINESS_UNITS]) || !$data[static::FIELD_ASSIGNED_BUSINESS_UNITS]) {
555
                    return;
556
                }
557
558
                $assignedCompanyIds = array_map('intval', $data[static::FIELD_ASSIGNED_COMPANIES]);
559
                $assignedBusinessUnitIds = array_map('intval', $data[static::FIELD_ASSIGNED_BUSINESS_UNITS]);
560
561
                $companyBusinessUnitFacade = $this->getFactory()->getCompanyBusinessUnitFacade();
562
                $businessUnitCollection = $companyBusinessUnitFacade->getCompanyBusinessUnitCollection(
563
                    (new CompanyBusinessUnitCriteriaFilterTransfer())->setCompanyIds($assignedCompanyIds),
564
                );
565
566
                $companyBusinessUnits = [];
567
                foreach ($businessUnitCollection->getCompanyBusinessUnits() as $businessUnit) {
568
                    if ($businessUnit->getFkCompany() && $businessUnit->getIdCompanyBusinessUnit()) {
569
                        $companyId = $businessUnit->getFkCompany();
570
                        $businessUnitId = $businessUnit->getIdCompanyBusinessUnit();
571
572
                        if (!isset($companyBusinessUnits[$companyId])) {
573
                            $companyBusinessUnits[$companyId] = [];
574
                        }
575
576
                        $companyBusinessUnits[$companyId][] = $businessUnitId;
577
                    }
578
                }
579
580
                $companyFacade = $this->getFactory()->getCompanyFacade();
581
                $companiesWithoutBusinessUnits = [];
582
583
                foreach ($assignedCompanyIds as $companyId) {
584
                    $hasSelectedBusinessUnit = false;
585
586
                    if (isset($companyBusinessUnits[$companyId])) {
587
                        foreach ($companyBusinessUnits[$companyId] as $businessUnitId) {
588
                            if (in_array($businessUnitId, $assignedBusinessUnitIds)) {
589
                                $hasSelectedBusinessUnit = true;
590
591
                                break;
592
                            }
593
                        }
594
                    }
595
596
                    if (!$hasSelectedBusinessUnit) {
597
                        $companyCollection = $companyFacade->getCompanyCollection(
598
                            (new CompanyCriteriaFilterTransfer())->setCompanyIds([$companyId]),
599
                        );
600
601
                        if ($companyCollection->getCompanies()->count() > 0) {
602
                            $company = $companyCollection->getCompanies()->getIterator()->current();
603
                            $companiesWithoutBusinessUnits[] = $company->getNameOrFail();
604
                        }
605
                    }
606
                }
607
608
                if ((bool)$companiesWithoutBusinessUnits) {
609
                    $errorMessage = sprintf(
610
                        'For each selected company, at least one of its business units must be selected. Missing business units for companies: %s.',
611
                        implode(', ', $companiesWithoutBusinessUnits),
612
                    );
613
614
                    $form->addError(new FormError($errorMessage));
615
                }
616
            },
617
        );
618
    }
619
620
    /**
621
     * @param \Generated\Shared\Transfer\SspAssetTransfer $sspAssetTransfer
622
     *
623
     * @return array<int>
624
     */
625
    protected function extractBusinessUnitsFromTransfer(SspAssetTransfer $sspAssetTransfer): array
626
    {
627
        $sspAssetAssignmentTransfers = $sspAssetTransfer->getBusinessUnitAssignments();
628
        if ($sspAssetAssignmentTransfers->count() === 0) {
629
            return [];
630
        }
631
632
        $businessUnitIds = [];
633
        foreach ($sspAssetAssignmentTransfers as $sspAssetAssignmentTransfer) {
634
            $companyBusinessUnitTransfer = $sspAssetAssignmentTransfer->getCompanyBusinessUnit();
635
            if ($companyBusinessUnitTransfer) {
636
                $businessUnitIds[$companyBusinessUnitTransfer->getNameOrFail()] = $companyBusinessUnitTransfer->getIdCompanyBusinessUnitOrFail();
637
            }
638
        }
639
640
        return $businessUnitIds;
641
    }
642
643
    /**
644
     * @param \Generated\Shared\Transfer\SspAssetTransfer $sspAssetTransfer
645
     *
646
     * @return array<int>
647
     */
648
    protected function extractCompaniesFromTransfer(SspAssetTransfer $sspAssetTransfer): array
649
    {
650
        $sspAssetAssignmentTransfers = $sspAssetTransfer->getBusinessUnitAssignments();
651
        if ($sspAssetAssignmentTransfers->count() === 0) {
652
            return [];
653
        }
654
655
        $companyIds = [];
656
        foreach ($sspAssetAssignmentTransfers as $sspAssetAssignmentTransfer) {
657
            $companyBusinessUnitTransfer = $sspAssetAssignmentTransfer->getCompanyBusinessUnit();
658
            if ($companyBusinessUnitTransfer) {
659
                $companyIds[$companyBusinessUnitTransfer->getCompanyOrFail()->getNameOrFail()] = $companyBusinessUnitTransfer->getCompanyOrFail()->getIdCompanyOrFail();
660
            }
661
        }
662
663
        return $companyIds;
664
    }
665
}
666