Completed
Push — 0.3-dev ( 291149...449c2f )
by Arnaud
14:26
created

FieldFactory::create()   C

Complexity

Conditions 8
Paths 12

Size

Total Lines 67
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 67
rs 6.6523
cc 8
eloc 34
nc 12
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace LAG\AdminBundle\Field\Factory;
4
5
use Exception;
6
use LAG\AdminBundle\Admin\Configuration\ApplicationConfiguration;
7
use LAG\AdminBundle\Field\Field;
8
use LAG\AdminBundle\Field\FieldInterface;
9
use LAG\AdminBundle\Field\TwigFieldInterface;
10
use LAG\AdminBundle\Field\TranslatableFieldInterface;
11
use Symfony\Component\OptionsResolver\OptionsResolver;
12
use Symfony\Component\Translation\TranslatorInterface;
13
use Twig_Environment;
14
15
/**
16
 * Field factory. Instances fields with its renderer.
17
 */
18
class FieldFactory
19
{
20
    /**
21
     * Application configuration
22
     *
23
     * @var ApplicationConfiguration
24
     */
25
    protected $configuration;
26
27
    /**
28
     * Field class mapping array, indexed by field type.
29
     *
30
     * @var array
31
     */
32
    protected $fieldsMapping = [];
33
34
    /**
35
     * Translator for field values.
36
     *
37
     * @var TranslatorInterface
38
     */
39
    protected $translator;
40
41
    /**
42
     * Twig engine.
43
     *
44
     * @var Twig_Environment
45
     */
46
    protected $twig;
47
48
    /**
49
     * FieldFactory constructor.
50
     *
51
     * @param ApplicationConfiguration $configuration
52
     * @param TranslatorInterface $translator
53
     * @param Twig_Environment $twig
54
     */
55
    public function __construct(
56
        ApplicationConfiguration $configuration,
57
        TranslatorInterface $translator,
58
        Twig_Environment $twig
59
    ) {
60
        $this->configuration = $configuration;
61
        $this->fieldsMapping = $configuration->getFieldsMapping(); // shortcut to field mapping array
62
        $this->translator = $translator;
63
        $this->twig = $twig;
64
    }
65
66
    /**
67
     * Create a new field with its renderer.
68
     *
69
     * @param $fieldName
70
     * @param array $configuration
71
     *
72
     * @return Field
73
     *
74
     * @throws Exception
75
     */
76
    public function create($fieldName, array $configuration = [])
77
    {
78
        $resolver = new OptionsResolver();
79
        $resolver->setDefaults([
80
            'type' => 'string',
81
            'options' => [],
82
        ]);
83
        // set allowed fields type from tagged services
84
        $resolver->setAllowedValues('type', array_keys($this->fieldsMapping));
85
        $resolver->setAllowedTypes('type', 'string');
86
        $resolver->setAllowedTypes('options', 'array');
87
88
        // resolve options
89
        $configuration = $resolver->resolve($configuration);
90
91
        // for collection of fields, we resolve the configuration of each item
92
        if ($configuration['type'] == 'collection') {
93
            $items = [];
94
95
            foreach ($configuration['options'] as $itemFieldName => $itemFieldConfiguration) {
96
97
                // configuration should be an array
98
                if (!$itemFieldConfiguration) {
99
                    $itemFieldConfiguration = [];
100
                }
101
                // type should exists
102
                if (!array_key_exists('type', $configuration)) {
103
                    throw new Exception("Missing type configuration for field {$itemFieldName}");
104
                }
105
                // create collection item
106
                $items[] = $this->create($itemFieldName, $itemFieldConfiguration);
107
            }
108
            // add created item to the field options
109
            $configuration['options'] = [
110
                'fields' => $items,
111
            ];
112
        }
113
        // instanciate field
114
        $fieldClass = $this->getFieldMapping($configuration['type']);
115
        $field = new $fieldClass();
116
117
        if (!($field instanceof FieldInterface)) {
118
            throw new Exception("Field class {$fieldClass} must implements " . FieldInterface::class);
119
        }
120
        $field->setName($fieldName);
121
        $field->setConfiguration($this->configuration);
122
123
        if ($field instanceof TranslatableFieldInterface) {
124
            $field->setTranslator($this->translator);
125
        }
126
        if ($field instanceof TwigFieldInterface) {
127
            $field->setTwig($this->twig);
128
        }
129
        // clear revolver from previous default configuration
130
        $resolver->clear();
131
132
        // configure field default options
133
        $field->configureOptions($resolver);
134
        // resolve options
135
        $options = $resolver->resolve($configuration['options']);
136
137
        // set options and value
138
        $field->setOptions($options);
139
140
141
        return $field;
142
    }
143
144
    /**
145
     * Return field class according to the field type. If the type is not present in the field mapping array, an
146
     * exception will be thrown.
147
     *
148
     * @param $type
149
     * @return string
150
     * @throws Exception
151
     */
152
    public function getFieldMapping($type)
153
    {
154
        if (!array_key_exists($type, $this->fieldsMapping)) {
155
            throw new Exception("Field type {$type} not found in field mapping. Check your configuration");
156
        }
157
158
        return $this->fieldsMapping[$type];
159
    }
160
}
161