Completed
Push — master ( fac271...8ddb27 )
by Vladimir
02:08
created

DefaultManipulator::getFieldsConfig()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 11
nc 2
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
/**
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
        $formFields = $formOptions['fields'];
40
41
        $objectFields = $this->objectInfo->getFieldsConfig($class);
42
        $objectFields = $this->filterObjectFields($objectFields, $formOptions['excluded_fields']);
43
44
        if (!empty($formFields)) {
45
            return $objectFields;
46
        }
47
48
        $this->checkUnknownFields($formFields, $objectFields, $class);
49
50
        $fieldsConfig = $this->filterFields($formFields);
51
        array_walk($fieldsConfig, function (&$v, $k, $d) {$v += $d[$k]; }, $objectFields);
52
53
        return $fieldsConfig;
54
    }
55
56
    /**
57
     * @param array  $formFields
58
     * @param array  $objectFields
59
     * @param string $class
60
     *
61
     * @throws \RuntimeException
62
     */
63
    private function checkUnknownFields($formFields, $objectFields, $class)
64
    {
65
        $unknowsFields = array_diff_key($formFields, $objectFields);
66
        if (!empty($unknowsFields)) {
67
            throw new \RuntimeException(
68
                sprintf("Field(s) '%s' doesn't exist in %s", implode(', ', $unknowsFields), $class)
69
            );
70
        }
71
    }
72
73
    /**
74
     * @param FormInterface $form
75
     *
76
     * @return string
77
     */
78
    private function getDataClass(FormInterface $form)
79
    {
80
        // Simple case, data_class from current form
81
        if ($dataClass = $form->getConfig()->getDataClass()) {
82
            return ClassUtils::getRealClass($dataClass);
83
        }
84
85
        // Advanced case, loop parent form to get closest fill data_class
86
        while ($formParent = $form->getParent()) {
87
            if (!$dataClass = $formParent->getConfig()->getDataClass()) {
88
                $form = $formParent;
89
                continue;
90
            }
91
92
            return $this->objectInfo->getAssociationTargetClass($dataClass, $form->getName());
93
        }
94
    }
95
96
    /**
97
     * @param array $objectFieldsConfig
98
     * @param array $formExcludedFields
99
     *
100
     * @return array
101
     */
102
    private function filterObjectFields(array $objectFieldsConfig, array $formExcludedFields)
103
    {
104
        $excludedFields = array_fill_keys(array_merge($this->globalExcludedFields, $formExcludedFields), []);
105
106
        return array_diff_key($objectFieldsConfig, $excludedFields);
107
    }
108
109
    private function filterFields($fields)
110
    {
111
        return array_filter($fields, function ($v) {return !(null === $v || (array_key_exists('display', $v) && !$v['display'])); });
112
    }
113
}
114