Passed
Push — master ( d3a6ec...c169ec )
by Vladimir
02:30 queued 15s
created

FormManipulator::__construct()   A

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
    /**
24
     * @param FieldsExtractorInterface $fieldsExtractor
25
     * @param array                    $globalExcludedFields
26
     */
27
    public function __construct(FieldsExtractorInterface $fieldsExtractor, array $globalExcludedFields = [])
28
    {
29
        $this->fieldsExtractor = $fieldsExtractor;
30
        $this->globalExcludedFields = $globalExcludedFields;
31
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public function getFieldsConfig(FormInterface $form)
37
    {
38
        $class = $this->getDataClass($form);
39
        $formOptions = $form->getConfig()->getOptions();
40
        $formFields = $formOptions['fields'];
41
42
        $objectFields = $this->fieldsExtractor->getFieldsConfig($class);
43
        $objectFields = $this->filterObjectFields($objectFields, $formOptions['excluded_fields']);
44
45
        if (empty($formFields)) {
46
            return $objectFields;
47
        }
48
49
        $this->checkUnknownFields($formFields, $objectFields, $class);
50
51
        $fieldsConfig = $this->filterFields($formFields);
52
        array_walk(
53
            $fieldsConfig,
54
            function (&$v, $k, $d) {
55
                $v += $d[$k];
56
            },
57
            $objectFields
58
        );
59
60
        return $fieldsConfig;
61
    }
62
63
    /**
64
     * @param array  $formFields
65
     * @param array  $objectFields
66
     * @param string $class
67
     *
68
     * @throws \RuntimeException
69
     */
70
    private function checkUnknownFields($formFields, $objectFields, $class)
71
    {
72
        $unknowsFields = array_keys(array_diff_key($formFields, $objectFields));
73
        if (!empty($unknowsFields)) {
74
            throw new \RuntimeException(
75
                sprintf("Field(s) '%s' doesn't exist in %s", implode(', ', $unknowsFields), $class)
76
            );
77
        }
78
    }
79
80
    /**
81
     * @param FormInterface $form
82
     *
83
     * @return string
84
     */
85
    private function getDataClass(FormInterface $form)
86
    {
87
        // Simple case, data_class from current form
88
        if ($dataClass = $form->getConfig()->getDataClass()) {
89
            return ClassUtils::getRealClass($dataClass);
90
        }
91
92
        // Advanced case, loop parent form to get closest fill data_class
93
        while ($formParent = $form->getParent()) {
94
            if (!$dataClass = $formParent->getConfig()->getDataClass()) {
95
                $form = $formParent;
96
97
                continue;
98
            }
99
100
            return $this->fieldsExtractor->getAssociationTargetClass($dataClass, $form->getName());
101
        }
102
    }
103
104
    /**
105
     * @param array $objectFieldsConfig
106
     * @param array $formExcludedFields
107
     *
108
     * @return array
109
     */
110
    private function filterObjectFields(array $objectFieldsConfig, array $formExcludedFields)
111
    {
112
        $excludedFields = array_fill_keys(array_merge($this->globalExcludedFields, $formExcludedFields), []);
113
114
        return array_diff_key($objectFieldsConfig, $excludedFields);
115
    }
116
117
    private function filterFields($fields)
118
    {
119
        return array_filter(
120
            $fields,
121
            function ($v) {
122
                return !(null === $v || (array_key_exists('display', $v) && !$v['display']));
123
            }
124
        );
125
    }
126
}
127