Completed
Branch master (01610a)
by Arnaud
06:29
created

FieldFactory::create()   C

Complexity

Conditions 8
Paths 12

Size

Total Lines 67
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 2
Bugs 2 Features 1
Metric Value
c 2
b 2
f 1
dl 0
loc 67
ccs 0
cts 40
cp 0
rs 6.6523
cc 8
eloc 34
nc 12
nop 2
crap 72

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\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
    public function __construct(
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