FormManipulator::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
1
<?php
2
3
namespace Koff\Bundle\I18nFormBundle\Form\Manipulator;
4
5
use Doctrine\Common\Util\ClassUtils;
6
use Koff\Bundle\I18nFormBundle\Extractor\FieldsExtractorInterface;
7
use Symfony\Component\Form\FormInterface;
8
9
/**
10
 * Class DefaultManipulator.
11
 *
12
 * @author David ALLIX
13
 * @author Sadicov Vladimir <[email protected]>
14
 */
15
class FormManipulator implements FormManipulatorInterface
16
{
17
    /** @var FieldsExtractorInterface */
18
    private $fieldsExtractor;
19
20
    /** @var array */
21
    private $globalExcludedFields;
22
23
    public function __construct(FieldsExtractorInterface $fieldsExtractor, array $globalExcludedFields = [])
24
    {
25
        $this->fieldsExtractor = $fieldsExtractor;
26
        $this->globalExcludedFields = $globalExcludedFields;
27
    }
28
29
    /**
30
     * {@inheritdoc}
31
     */
32
    public function getFieldsConfig(FormInterface $form): array
33
    {
34
        $class = $this->getDataClass($form);
35
        $formOptions = $form->getConfig()->getOptions();
36
        $formFields = $formOptions['fields'];
37
38
        $objectFields = $this->fieldsExtractor->getFieldsConfig($class);
39
        $objectFields = $this->filterObjectFields($objectFields, $formOptions['excluded_fields']);
40
41
        if (empty($formFields)) {
42
            return $objectFields;
43
        }
44
45
        $this->checkUnknownFields($formFields, $objectFields, $class);
46
47
        $fieldsConfig = $this->filterFields($formFields);
48
        array_walk(
49
            $fieldsConfig,
50
            function (&$v, $k, $d) {
51
                $v += $d[$k];
52
            },
53
            $objectFields
54
        );
55
56
        return $fieldsConfig;
57
    }
58
59
    /**
60
     * @param array  $formFields
61
     * @param array  $objectFields
62
     * @param string $class
63
     *
64
     * @throws \RuntimeException
65
     */
66
    private function checkUnknownFields($formFields, $objectFields, $class)
67
    {
68
        $unknowsFields = array_keys(array_diff_key($formFields, $objectFields));
69
        if (!empty($unknowsFields)) {
70
            throw new \RuntimeException(sprintf("Field(s) '%s' doesn't exist in %s", implode(', ', $unknowsFields), $class));
71
        }
72
    }
73
74
    /**
75
     * @return string
76
     */
77
    private function getDataClass(FormInterface $form)
78
    {
79
        // Simple case, data_class from current form
80
        if ($dataClass = $form->getConfig()->getDataClass()) {
81
            return ClassUtils::getRealClass($dataClass);
82
        }
83
84
        // Advanced case, loop parent form to get closest fill data_class
85
        while ($formParent = $form->getParent()) {
86
            if (!$dataClass = $formParent->getConfig()->getDataClass()) {
87
                $form = $formParent;
88
89
                continue;
90
            }
91
92
            return $this->fieldsExtractor->getAssociationTargetClass($dataClass, $form->getName());
93
        }
94
    }
95
96
    private function filterObjectFields(array $objectFieldsConfig, array $formExcludedFields): array
97
    {
98
        $excludedFields = array_fill_keys(array_merge($this->globalExcludedFields, $formExcludedFields), []);
99
100
        return array_diff_key($objectFieldsConfig, $excludedFields);
101
    }
102
103
    private function filterFields($fields)
104
    {
105
        return array_filter(
106
            $fields,
107
            function ($v) {
108
                return !(null === $v || (\array_key_exists('display', $v) && !$v['display']));
109
            }
110
        );
111
    }
112
}
113