Completed
Pull Request — dev (#43)
by Arnaud
03:21
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 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