Passed
Push — master ( 876e5c...fac271 )
by Vladimir
02:11
created

DefaultManipulator::filterObjectFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
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 Koff\Bundle\I18nFormBundle\ObjectInfo\ObjectInfoInterface;
6
use Doctrine\Common\Util\ClassUtils;
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 DefaultManipulator implements FormManipulatorInterface
16
{
17
    /** @var ObjectInfoInterface */
18
    private $objectInfo;
19
    /** @var array */
20
    private $globalExcludedFields;
21
22
    /**
23
     * @param ObjectInfoInterface $objectInfo
24
     * @param array               $globalExcludedFields
25
     */
26
    public function __construct(ObjectInfoInterface $objectInfo, array $globalExcludedFields = [])
27
    {
28
        $this->objectInfo = $objectInfo;
29
        $this->globalExcludedFields = $globalExcludedFields;
30
    }
31
32
    /**
33
     * {@inheritdoc}
34
     */
35
    public function getFieldsConfig(FormInterface $form)
36
    {
37
        $class = $this->getDataClass($form);
38
        $formOptions = $form->getConfig()->getOptions();
39
40
        $formFields = $formOptions['fields'];
41
42
        $objectFields = $this->objectInfo->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
53
        array_walk(
54
            $fieldsConfig,
55
            function (&$v, $k, $d) {
56
                $v += $d[$k];
57
            },
58
            $objectFields
59
        );
60
61
        return $fieldsConfig;
62
    }
63
64
    /**
65
     * @param array  $formFields
66
     * @param array  $objectFields
67
     * @param string $class
68
     *
69
     * @throws \RuntimeException
70
     */
71
    private function checkUnknownFields($formFields, $objectFields, $class)
72
    {
73
        $unknowsFields = array_diff_key($formFields, $objectFields);
74
        if (!empty($unknowsFields)) {
75
            throw new \RuntimeException(
76
                sprintf("Field(s) '%s' doesn't exist in %s", implode(', ', $unknowsFields), $class)
77
            );
78
        }
79
    }
80
81
    /**
82
     * @param FormInterface $form
83
     *
84
     * @return string
85
     */
86
    private function getDataClass(FormInterface $form)
87
    {
88
        // Simple case, data_class from current form
89
        if ($dataClass = $form->getConfig()->getDataClass()) {
90
            return ClassUtils::getRealClass($dataClass);
91
        }
92
93
        // Advanced case, loop parent form to get closest fill data_class
94
        while ($formParent = $form->getParent()) {
95
            if (!$dataClass = $formParent->getConfig()->getDataClass()) {
96
                $form = $formParent;
97
                continue;
98
            }
99
100
            return $this->objectInfo->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