Passed
Pull Request — master (#116)
by Arnaud
03:41
created

FormFactory::addFormTransformers()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 36
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 22
nc 4
nop 3
dl 0
loc 36
rs 8.6346
c 0
b 0
f 0
1
<?php
2
3
namespace LAG\AdminBundle\Factory;
4
5
use LAG\AdminBundle\Admin\ActionInterface;
6
use LAG\AdminBundle\Admin\AdminInterface;
7
use LAG\AdminBundle\Configuration\AdminConfiguration;
8
use LAG\AdminBundle\DataProvider\DataProviderInterface;
9
use LAG\AdminBundle\Event\Events;
10
use LAG\AdminBundle\Event\Events\FormEvent;
11
use LAG\AdminBundle\Exception\Exception;
12
use LAG\AdminBundle\Field\Definition\FieldDefinitionInterface;
13
use LAG\AdminBundle\Utils\FormUtils;
14
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15
use Symfony\Component\Form\CallbackTransformer;
16
use Symfony\Component\Form\Extension\Core\Type\FormType;
17
use Symfony\Component\Form\FormBuilderInterface;
18
use Symfony\Component\Form\FormFactoryInterface;
1 ignored issue
show
Bug introduced by
This use statement conflicts with another class in this namespace, LAG\AdminBundle\Factory\FormFactoryInterface. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
19
use Symfony\Component\Form\FormInterface;
20
use Symfony\Component\HttpFoundation\Request;
21
use Symfony\Component\Yaml\Yaml;
22
23
class FormFactory implements \LAG\AdminBundle\Factory\FormFactoryInterface
24
{
25
    /**
26
     * @var DataProviderFactory
27
     */
28
    private $dataProviderFactory;
29
30
    /**
31
     * @var FormFactoryInterface
32
     */
33
    private $formFactory;
34
35
    /**
36
     * @var EventDispatcherInterface
37
     */
38
    private $eventDispatcher;
39
40
    public function __construct(
41
        DataProviderFactory $dataProviderFactory,
42
        FormFactoryInterface $formFactory,
43
        EventDispatcherInterface $eventDispatcher
44
    ) {
45
        $this->dataProviderFactory = $dataProviderFactory;
46
        $this->formFactory = $formFactory;
47
        $this->eventDispatcher = $eventDispatcher;
48
    }
49
50
    public function createEntityForm(AdminInterface $admin, Request $request, $entity = null): FormInterface
51
    {
52
        $dataProvider = $this->getDataProvider($admin->getConfiguration());
53
54
        if (null === $entity) {
55
            $entity = $dataProvider->create($admin);
56
        }
57
        $formType = $admin->getConfiguration()->get('form');
58
59
        if (null === $formType) {
60
            $builder = $this
61
                ->formFactory
62
                ->createBuilder(FormType::class, $entity, [
63
                    'label' => false,
64
                ])
65
            ;
66
            $event = new FormEvent($admin, $request);
67
            $this->eventDispatcher->dispatch(Events::FORM_PRE_CREATE_ENTITY_FORM, $event);
68
69
            foreach ($event->getFieldDefinitions() as $field => $definition) {
70
                if (!$definition instanceof FieldDefinitionInterface) {
71
                    throw new Exception(
72
                        'The field definition should implements "'.FieldDefinitionInterface::class.'", got "'.gettype($definition)
73
                    );
74
                }
75
                // Usually we do not want to edit those values in a Form
76
                if (in_array($field, [
77
                        'createdAt',
78
                        'updatedAt',
79
                    ]) && 'datetime' === $definition->getType()) {
80
                    continue;
81
                }
82
                $formType = FormUtils::convertShortFormType($definition->getType());
83
                $formOptions = FormUtils::getFormTypeOptions($definition->getType());
84
                $formOptions = array_merge($formOptions, $definition->getOptions());
85
86
                $builder->add($field, $formType, $formOptions);
87
                $this->addFormTransformers($builder, $field, $definition->getType());
88
            }
89
            $form = $builder->getForm();
90
        } else {
91
            $form = $this
92
                ->formFactory
93
                ->create($formType, $entity)
94
            ;
95
        }
96
97
        return $form;
98
    }
99
100
    public function createDeleteForm(ActionInterface $action, Request $request, $entity): FormInterface
101
    {
102
        $form = $this
103
            ->formFactory
104
            ->create($action->getConfiguration()->get('form'), $entity)
105
        ;
106
107
        return $form;
108
    }
109
110
    private function getDataProvider(AdminConfiguration $configuration): DataProviderInterface
111
    {
112
        return $this
113
            ->dataProviderFactory
114
            ->get($configuration->get('data_provider'))
115
        ;
116
    }
117
118
    private function addFormTransformers(FormBuilderInterface $builder, string $field, ?string $type): void
119
    {
120
        if ('array' === $type) {
121
            $builder
122
                ->get($field)
123
                ->addModelTransformer(new CallbackTransformer(function (?array $value) {
124
                    if (null === $value) {
0 ignored issues
show
introduced by
The condition null === $value is always false.
Loading history...
125
                        $value = [];
126
                    }
127
128
                    return Yaml::dump($value);
129
                }, function ($value) {
130
                    if (null === $value) {
131
                        return [];
132
                    }
133
134
                    return Yaml::parse($value);
135
                }))
136
            ;
137
        }
138
139
        if ('simple_array' === $type) {
140
            $builder
141
                ->get($field)
142
                ->addModelTransformer(new CallbackTransformer(function (?array $value) {
143
                    if (null === $value) {
0 ignored issues
show
introduced by
The condition null === $value is always false.
Loading history...
144
                        $value = [];
145
                    }
146
147
                    return implode(',', $value);
148
                }, function ($value) {
149
                    if (null === $value) {
150
                        return [];
151
                    }
152
153
                    return explode(',', $value);
154
                }))
155
            ;
156
        }
157
    }
158
}
159