Passed
Push — master ( c7b63e...431875 )
by Vladimir
02:17
created

DefaultManipulator::getFieldsConfig()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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