Completed
Push — master ( 9aa567...23105f )
by Andreas
18:08
created

schema   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 227
Duplicated Lines 0 %

Test Coverage

Coverage 94.29%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 123
dl 0
loc 227
ccs 99
cts 105
cp 0.9429
rs 8.8
c 1
b 0
f 0
wmc 45

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A get_field() 0 6 2
A get_l10n() 0 8 3
A get() 0 3 1
A get_defaults() 0 9 3
A has_field() 0 3 1
A complete_fields() 0 4 2
A set() 0 5 2
A set_name() 0 3 1
A get_name() 0 3 1
D resolve_field_options() 0 131 28

How to fix   Complexity   

Complex Class

Complex classes like schema often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use schema, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @copyright CONTENT CONTROL GmbH, http://www.contentcontrol-berlin.de
4
 */
5
6
namespace midcom\datamanager;
7
8
use midcom_error;
9
use Symfony\Component\OptionsResolver\Options;
10
use Symfony\Component\OptionsResolver\OptionsResolver;
11
use midcom;
12
use midcom_core_context;
13
use midcom_services_i18n_l10n;
14
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
15
16
/**
17
 * Experimental schema class
18
 */
19
class schema
20
{
21
    /**
22
     * @var array
23
     */
24
    private $defaults = [
25
        'operations' => ['save' => '', 'cancel' => ''],
26
        'fields' => [],
27
        'customdata' => [],
28
        'validation' => [],
29
        'action' => ''
30
    ];
31
32
    /**
33
     * @var array
34
     */
35
    private $config = [];
36
37
    /**
38
     * @var string
39
     */
40
    private $name = 'default';
41
42 266
    public function __construct(array $config)
43
    {
44 266
        $this->config = array_merge($this->defaults, $config);
45 266
        $this->complete_fields();
46 266
    }
47
48 263
    public function set_name(string $name)
49
    {
50 263
        $this->name = $name;
51 263
    }
52
53 48
    public function get_name() : string
54
    {
55 48
        return $this->name;
56
    }
57
58 247
    public function get(string $key)
59
    {
60 247
        return $this->config[$key];
61
    }
62
63 12
    public function set(string $key, $value)
64
    {
65 12
        $this->config[$key] = $value;
66 12
        if ($key === 'fields') {
67 8
            $this->complete_fields();
68
        }
69 12
    }
70
71 130
    public function has_field(string $name) : bool
72
    {
73 130
        return array_key_exists($name, $this->config['fields']);
74
    }
75
76
    /**
77
     * Returns reference to field config (for on the fly modification)
78
     */
79
    public function & get_field(string $name) : array
80
    {
81 39
        if (!$this->has_field($name)) {
82
            throw new \midcom_error('Field ' . $name . ' is not available in this schema');
83
        }
84 39
        return $this->config['fields'][$name];
85
    }
86
87 233
    public function get_defaults() : array
88
    {
89 233
        $defaults = [];
90 233
        foreach ($this->config['fields'] as $name => $config) {
91 231
            if (!empty($config['default'])) {
92 40
                $defaults[$name] = $config['default'];
93
            }
94
        }
95 233
        return $defaults;
96
    }
97
98 140
    public function get_l10n() : midcom_services_i18n_l10n
99
    {
100
        // Populate the l10n_schema member
101 140
        $l10n_name = $this->config['l10n_db'] ?? midcom_core_context::get()->get_key(MIDCOM_CONTEXT_COMPONENT);
102 140
        if (!$l10n_name || !midcom::get()->componentloader->is_installed($l10n_name)) {
103 1
            $l10n_name = 'midcom';
104
        }
105 140
        return midcom::get()->i18n->get_l10n($l10n_name);
106
    }
107
108 266
    private function complete_fields()
109
    {
110 266
        foreach ($this->config['fields'] as $name => &$config) {
111 264
            $config = $this->resolve_field_options($config, $name);
112
        }
113 266
    }
114
115 264
    private function resolve_field_options(array $config, string $name) : array
116
    {
117 264
        $resolver = new OptionsResolver();
118
119 264
        $resolver->setDefaults(array_merge([
120 264
            'title' => '',
121
            'description' => '',
122
            'type' => null,
123
            'type_config' => [],
124
            'widget' => null,
125
            'widget_config' => [],
126
            'required' => false,
127
            'readonly' => false,
128
            'hidden' => false,
129
            'default' => null,
130
            'storage' => '__UNSET__',
131
            'index_method' => 'auto',
132
            'index_merge_with_content' => true,
133
            'start_fieldset' => null,
134
            'end_fieldset' => null,
135
            'validation' => [],
136
            'helptext' => null,
137
            'write_privilege' => null,
138
            'customdata' => []
139
        ], $config));
140
141
        $normalize_widget = function (Options $options, $value) {
142 264
            if ($value == 'text') {
143 253
                if (!empty($options['widget_config']['hideinput'])) {
144 1
                    return PasswordType::class;
145
                }
146 253
                if ($options['type'] === 'number') {
147 149
                    return 'number';
148
                }
149 244
                if ($options['type'] === 'urlname') {
150 38
                    return 'urlname';
151
                }
152 244
                if (!empty($options['validation'])) {
153 40
                    foreach ($options['validation'] as $rule) {
154 40
                        if (is_array($rule) && $rule['type'] === 'email') {
155 40
                            return 'email';
156
                        }
157
                    }
158
                }
159
            }
160 264
            if ($value == 'select' && !empty($options['type_config']['allow_other'])) {
161 16
                return 'other';
162
            }
163 264
            return $value;
164 264
        };
165
166
        $normalize_storage = function (Options $options, $value) use ($name) {
167
            $default = [
168 264
                'location' => 'parameter',
169 264
                'domain' => 'midcom.helper.datamanager2',
170 264
                'name' => $name
171
            ];
172 264
            if ($value === '__UNSET__') {
173 145
                return $default;
174
            }
175 262
            if ($options['type'] === 'privilege') {
176
                return [
177 5
                    'location' => 'privilege',
178 5
                    'name' => $name
179
                ];
180
            }
181 260
            if ($options['type'] === 'tags' || $value === null) {
182 116
                return null;
183
            }
184 253
            if (is_string($value)) {
185 247
                if ($value === 'metadata') {
186 100
                    return ['location' => $value, 'name' => $name];
187
                }
188 164
                if ($value === 'parameter') {
189 32
                    return $default;
190
                }
191 163
                return ['location' => $value];
192
            }
193 132
            if (strtolower($value['location']) === 'parameter') {
194 106
                $value['location'] = strtolower($value['location']);
195 106
                if (!array_key_exists('domain', $value)) {
196
                    $value['domain'] = 'midcom.helper.datamanager2';
197
                }
198
            }
199 132
            if (strtolower($value['location']) === 'configuration') {
200 129
                $value['location'] = 'parameter';
201
            }
202 132
            return $value;
203 264
        };
204
205
        $normalize_validation = function (Options $options, $value) {
206 264
            $validation = [];
207
208 264
            foreach ((array) $value as $key => $rule) {
209 40
                if (!is_array($rule)) {
210 40
                    if (is_object($rule)) {
211
                        $validation[] = $rule;
212
                        continue;
213
                    }
214 40
                    $rule = ['type' => $rule];
215 2
                } elseif (!array_key_exists('type', $rule)) {
216
                    throw new midcom_error("Missing validation rule type for rule {$key} on field {$options['name']}, this is a required option.");
217 2
                } elseif (   $rule['type'] == 'compare'
218 2
                          && !array_key_exists('compare_with', $rule)) {
219
                    throw new midcom_error("Missing compare_with option for compare type rule {$key} on field {$options['name']}, this is a required option.");
220
                }
221
222
                $defaults = [
223 40
                    'message' => "validation failed: {$rule['type']}",
224 40
                    'format' => ''
225
                ];
226
227 40
                $validation[] = array_merge($defaults, $rule);
228
            }
229
230 264
            return $validation;
231 264
        };
232
233
        $normalize_type = function(Options $options, $value) {
234 264
            if ($value === 'tags') {
235 143
                return 'net_nemein_tag_datamanager_storage';
236
            }
237 264
            return $value;
238 264
        };
239
240 264
        $resolver->setNormalizer('storage', $normalize_storage);
241 264
        $resolver->setNormalizer('widget', $normalize_widget);
242 264
        $resolver->setNormalizer('validation', $normalize_validation);
243 264
        $resolver->setNormalizer('type', $normalize_type);
244
245 264
        return $resolver->resolve($config);
246
    }
247
}
248