Completed
Pull Request — dev (#43)
by Arnaud
03:21
created

FieldFactory::getFieldMapping()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 8
ccs 0
cts 4
cp 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
crap 6
1
<?php
2
3
namespace LAG\AdminBundle\Field\Factory;
4
5
use Exception;
6
use LAG\AdminBundle\Application\Configuration\ApplicationConfiguration;
7
use LAG\AdminBundle\Configuration\Factory\ConfigurationFactory;
8
use LAG\AdminBundle\Field\Field;
9
use LAG\AdminBundle\Field\FieldInterface;
10
use LAG\AdminBundle\Field\TwigFieldInterface;
11
use LAG\AdminBundle\Field\TranslatableFieldInterface;
12
use Symfony\Component\OptionsResolver\OptionsResolver;
13
use Symfony\Component\Translation\TranslatorInterface;
14
use Twig_Environment;
15
16
/**
17
 * Field factory. Instances fields with its renderer.
18
 */
19
class FieldFactory
20
{
21
    /**
22
     * Application configuration
23
     *
24
     * @var ApplicationConfiguration
25
     */
26
    protected $configuration;
27
28
    /**
29
     * Field class mapping array, indexed by field type.
30
     *
31
     * @var array
32
     */
33
    protected $fieldsMapping = [];
34
35
    /**
36
     * Translator for field values.
37
     *
38
     * @var TranslatorInterface
39
     */
40
    protected $translator;
41
42
    /**
43
     * Twig engine.
44
     *
45
     * @var Twig_Environment
46
     */
47
    protected $twig;
48
49
    /**
50
     * FieldFactory constructor.
51
     *
52
     * @param ConfigurationFactory $configurationFactory
53
     * @param TranslatorInterface $translator
54
     * @param Twig_Environment $twig
55
     */
56 View Code Duplication
    public function __construct(
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
57
        ConfigurationFactory $configurationFactory,
58
        TranslatorInterface $translator,
59
        Twig_Environment $twig
60
    ) {
61
        $this->configuration = $configurationFactory->getApplicationConfiguration();
62
        $this->fieldsMapping = $this
63
            ->configuration
64
            ->getParameter('fields_mapping'); // shortcut to field mapping array
65
        $this->translator = $translator;
66
        $this->twig = $twig;
67
    }
68
69
    /**
70
     * Create a new field with its renderer.
71
     *
72
     * @param $fieldName
73
     * @param array $configuration
74
     *
75
     * @return Field
76
     *
77
     * @throws Exception
78
     */
79
    public function create($fieldName, array $configuration = [])
80
    {
81
        $resolver = new OptionsResolver();
82
        $resolver->setDefaults([
83
            'type' => 'string',
84
            'options' => [],
85
        ]);
86
        // set allowed fields type from tagged services
87
        $resolver->setAllowedValues('type', array_keys($this->fieldsMapping));
88
        $resolver->setAllowedTypes('type', 'string');
89
        $resolver->setAllowedTypes('options', 'array');
90
91
        // resolve options
92
        $configuration = $resolver->resolve($configuration);
93
94
        // for collection of fields, we resolve the configuration of each item
95
        if ($configuration['type'] == 'collection') {
96
            $items = [];
97
98
            foreach ($configuration['options'] as $itemFieldName => $itemFieldConfiguration) {
99
100
                // configuration should be an array
101
                if (!$itemFieldConfiguration) {
102
                    $itemFieldConfiguration = [];
103
                }
104
                // type should exists
105
                if (!array_key_exists('type', $configuration)) {
106
                    throw new Exception("Missing type configuration for field {$itemFieldName}");
107
                }
108
                // create collection item
109
                $items[] = $this->create($itemFieldName, $itemFieldConfiguration);
110
            }
111
            // add created item to the field options
112
            $configuration['options'] = [
113
                'fields' => $items,
114
            ];
115
        }
116
        // instanciate field
117
        $fieldClass = $this->getFieldMapping($configuration['type']);
118
        $field = new $fieldClass();
119
120
        if (!($field instanceof FieldInterface)) {
121
            throw new Exception("Field class {$fieldClass} must implements ".FieldInterface::class);
122
        }
123
        $field->setName($fieldName);
124
        $field->setApplicationConfiguration($this->configuration);
125
126
        if ($field instanceof TranslatableFieldInterface) {
127
            $field->setTranslator($this->translator);
128
        }
129
        if ($field instanceof TwigFieldInterface) {
130
            $field->setTwig($this->twig);
131
        }
132
        // clear revolver from previous default configuration
133
        $resolver->clear();
134
135
        // configure field default options
136
        $field->configureOptions($resolver);
137
        
138
        // resolve options
139
        $options = $resolver->resolve($configuration['options']);
140
141
        // set options
142
        $field->setOptions($options);
143
        
144
        return $field;
145
    }
146
147
    /**
148
     * Return field class according to the field type. If the type is not present in the field mapping array, an
149
     * exception will be thrown.
150
     *
151
     * @param $type
152
     * @return string
153
     * @throws Exception
154
     */
155
    public function getFieldMapping($type)
156
    {
157
        if (!array_key_exists($type, $this->fieldsMapping)) {
158
            throw new Exception("Field type {$type} not found in field mapping. Check your configuration");
159
        }
160
161
        return $this->fieldsMapping[$type];
162
    }
163
}
164