Completed
Pull Request — master (#116)
by Arnaud
05:17
created

FormFactory   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 64
dl 0
loc 121
rs 10
c 0
b 0
f 0
wmc 17

5 Methods

Rating   Name   Duplication   Size   Complexity  
A createDeleteForm() 0 8 1
B addFormTransformers() 0 36 7
B createEntityForm() 0 47 7
A getDataProvider() 0 5 1
A __construct() 0 4 1
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\Exception\Exception;
10
use LAG\AdminBundle\Field\Definition\FieldDefinitionInterface;
11
use LAG\AdminBundle\Utils\FormUtils;
12
use Symfony\Component\Form\CallbackTransformer;
13
use Symfony\Component\Form\Extension\Core\Type\FormType;
14
use Symfony\Component\Form\FormBuilderInterface;
15
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...
16
use Symfony\Component\Form\FormInterface;
17
use Symfony\Component\Yaml\Yaml;
18
19
class FormFactory implements \LAG\AdminBundle\Factory\FormFactoryInterface
20
{
21
    /**
22
     * @var DataProviderFactory
23
     */
24
    private $dataProviderFactory;
25
26
    /**
27
     * @var FormFactoryInterface
28
     */
29
    private $formFactory;
30
31
    public function __construct(DataProviderFactory $dataProviderFactory, FormFactoryInterface $formFactory)
32
    {
33
        $this->dataProviderFactory = $dataProviderFactory;
34
        $this->formFactory = $formFactory;
35
    }
36
37
    public function createEntityForm(AdminInterface $admin, $entity = null): FormInterface
38
    {
39
        $dataProvider = $this->getDataProvider($admin->getConfiguration());
40
41
        if (null === $entity) {
42
            $entity = $dataProvider->create($admin);
43
        }
44
        $formType = $admin->getConfiguration()->get('form');
45
46
        if (null === $formType) {
47
            $builder = $this
48
                ->formFactory
49
                ->createBuilder(FormType::class, $entity, [
50
                    'label' => false,
51
                ])
52
            ;
53
            $fields = $dataProvider->getFields($admin);
54
55
            foreach ($fields as $field => $definition) {
56
                if (!$definition instanceof FieldDefinitionInterface) {
57
                    throw new Exception(
58
                        'The field definition should implements "'.FieldDefinitionInterface::class.'", got "'.gettype($definition)
59
                    );
60
                }
61
                // Usually we do not want to edit those values in a Form
62
                if (in_array($field, [
63
                        'createdAt',
64
                        'updatedAt',
65
                    ]) && 'datetime' === $definition->getType()) {
66
                    continue;
67
                }
68
                $formType = FormUtils::convertShortFormType($definition->getType());
69
                $formOptions = FormUtils::getFormTypeOptions($definition->getType());
70
                $formOptions = array_merge($formOptions, $definition->getOptions());
71
72
                $builder->add($field, $formType, $formOptions);
73
                $this->addFormTransformers($builder, $field, $definition->getType());
74
            }
75
            $form = $builder->getForm();
76
        } else {
77
            $form = $this
78
                ->formFactory
79
                ->create($formType, $entity)
80
            ;
81
        }
82
83
        return $form;
84
    }
85
86
    public function createDeleteForm(ActionInterface $action, $entity): FormInterface
87
    {
88
        $form = $this
89
            ->formFactory
90
            ->create($action->getConfiguration()->get('form'), $entity)
91
        ;
92
93
        return $form;
94
    }
95
96
    private function getDataProvider(AdminConfiguration $configuration): DataProviderInterface
97
    {
98
        return $this
99
            ->dataProviderFactory
100
            ->get($configuration->get('data_provider'))
101
        ;
102
    }
103
104
    private function addFormTransformers(FormBuilderInterface $builder, string $field, ?string $type): void
105
    {
106
        if ('array' === $type) {
107
            $builder
108
                ->get($field)
109
                ->addModelTransformer(new CallbackTransformer(function (?array $value) {
110
                    if (null === $value) {
0 ignored issues
show
introduced by
The condition null === $value is always false.
Loading history...
111
                        $value = [];
112
                    }
113
114
                    return Yaml::dump($value);
115
                }, function ($value) {
116
                    if (null === $value) {
117
                        return [];
118
                    }
119
120
                    return Yaml::parse($value);
121
                }))
122
            ;
123
        }
124
125
        if ('simple_array' === $type) {
126
            $builder
127
                ->get($field)
128
                ->addModelTransformer(new CallbackTransformer(function (?array $value) {
129
                    if (null === $value) {
0 ignored issues
show
introduced by
The condition null === $value is always false.
Loading history...
130
                        $value = [];
131
                    }
132
133
                    return implode(',', $value);
134
                }, function ($value) {
135
                    if (null === $value) {
136
                        return [];
137
                    }
138
139
                    return explode(',', $value);
140
                }))
141
            ;
142
        }
143
    }
144
}
145