Passed
Push — master ( 48f5cf...31dc4c )
by Andreas
20:18
created

midgard_admin_asgard_handler_component_configuration   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 291
Duplicated Lines 0 %

Test Coverage

Coverage 55.42%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 159
c 1
b 0
f 0
dl 0
loc 291
ccs 92
cts 166
cp 0.5542
rs 8.5599
wmc 48

11 Methods

Rating   Name   Duplication   Size   Complexity  
B save_configuration() 0 26 7
A _handler_view() 0 9 1
A _show_view() 0 17 3
B save_topic() 0 32 11
B save_snippet() 0 41 6
B render() 0 27 7
A _prepare_breadcrumbs() 0 12 1
A _prepare_toolbar() 0 16 1
B _handler_edit() 0 59 8
A _load_configs() 0 10 2
A _on_initialize() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like midgard_admin_asgard_handler_component_configuration 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 midgard_admin_asgard_handler_component_configuration, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @package midgard.admin.asgard
4
 * @author The Midgard Project, http://www.midgard-project.org
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
use midcom\datamanager\datamanager;
10
use Symfony\Component\HttpFoundation\Request;
11
12
/**
13
 * Component configuration handler
14
 *
15
 * @package midgard.admin.asgard
16
 */
17
class midgard_admin_asgard_handler_component_configuration extends midcom_baseclasses_components_handler
18
{
19
    use midgard_admin_asgard_handler;
20
21
    private $_controller;
22
23 3
    public function _on_initialize()
24
    {
25 3
        $this->add_stylesheet(MIDCOM_STATIC_URL . '/midgard.admin.asgard/libconfig.css');
26 3
    }
27
28 2
    private function _prepare_toolbar(bool $is_view)
29
    {
30 2
        $view_url = $this->router->generate('components_configuration', ['component' => $this->_request_data['name']]);
31 2
        $edit_url = $this->router->generate('components_configuration_edit', ['component' => $this->_request_data['name']]);
32
        $buttons = [[
33 2
            MIDCOM_TOOLBAR_URL => $view_url,
34 2
            MIDCOM_TOOLBAR_LABEL => $this->_l10n_midcom->get('view'),
35 2
            MIDCOM_TOOLBAR_GLYPHICON => 'eye',
36 2
            MIDCOM_TOOLBAR_ENABLED => !$is_view
37
        ], [
38 2
            MIDCOM_TOOLBAR_URL => $edit_url,
39 2
            MIDCOM_TOOLBAR_LABEL => $this->_l10n_midcom->get('edit'),
40 2
            MIDCOM_TOOLBAR_GLYPHICON => 'pencil',
41 2
            MIDCOM_TOOLBAR_ENABLED => $is_view
42
        ]];
43 2
        $this->_request_data['asgard_toolbar']->add_items($buttons);
44 2
    }
45
46
    /**
47
     * Set the breadcrumb data
48
     */
49 2
    private function _prepare_breadcrumbs()
50
    {
51 2
        $this->add_breadcrumb($this->router->generate('welcome'), $this->_l10n->get($this->_component));
52 2
        $this->add_breadcrumb($this->router->generate('components'), $this->_l10n->get('components'));
53
54 2
        $this->add_breadcrumb(
55 2
            $this->router->generate('components_component', ['component' => $this->_request_data['name']]),
56 2
            $this->_i18n->get_string($this->_request_data['name'], $this->_request_data['name'])
57
        );
58 2
        $this->add_breadcrumb(
59 2
            $this->router->generate('components_configuration', ['component' => $this->_request_data['name']]),
60 2
            $this->_l10n_midcom->get('component configuration')
61
        );
62 2
    }
63
64 3
    private function _load_configs(string $component, midcom_db_topic $topic = null) : midcom_helper_configuration
65
    {
66 3
        $config = midcom_baseclasses_components_configuration::get($component, 'config');
67
68 3
        if ($topic) {
69 1
            $topic_config = new midcom_helper_configuration($topic, $component);
70 1
            $config->store($topic_config->_local, false);
71
        }
72
73 3
        return $config;
74
    }
75
76 1
    public function _handler_view(string $component, array &$data)
77
    {
78 1
        $data['name'] = $component;
79 1
        $data['config'] = $this->_load_configs($data['name']);
80
81 1
        $data['view_title'] = sprintf($this->_l10n->get('configuration for %s'), $data['name']);
82 1
        $this->_prepare_toolbar(true);
83 1
        $this->_prepare_breadcrumbs();
84 1
        return $this->get_response();
85
    }
86
87
    /**
88
     * @param array $data Data passed to the show method
89
     */
90 1
    public function _show_view(string $handler_id, array &$data)
91
    {
92 1
        midcom_show_style('midgard_admin_asgard_component_configuration_header');
93
94 1
        foreach ($data['config']->_global as $key => $value) {
95 1
            $data['key'] = $this->_i18n->get_string($key, $data['name']);
96 1
            $data['global'] = $this->render($value);
97
98 1
            if (isset($data['config']->_local[$key])) {
99
                $data['local'] = $this->render($data['config']->_local[$key]);
100
            } else {
101 1
                $data['local'] = $this->render(null);
102
            }
103
104 1
            midcom_show_style('midgard_admin_asgard_component_configuration_item');
105
        }
106 1
        midcom_show_style('midgard_admin_asgard_component_configuration_footer');
107 1
    }
108
109 1
    private function render($value)
110
    {
111 1
        $type = gettype($value);
112
113 1
        switch ($type) {
114 1
            case 'boolean':
115 1
                $result = '<i class="fa fa-' . ($value === true ? 'check' : 'times') . '"></i>';
116 1
                break;
117 1
            case 'array':
118 1
                $content = '<ul>';
119 1
                foreach ($value as $key => $val) {
120 1
                    $content .= "<li>{$key} => " . $this->render($val) . ",</li>\n";
121
                }
122 1
                $content .= '</ul>';
123 1
                $result = "<ul>\n<li>array</li>\n<li>(\n{$content}\n)</li>\n</ul>\n";
124 1
                break;
125 1
            case 'object':
126
                $result = '<strong>Object</strong>';
127
                break;
128 1
            case 'NULL':
129 1
                $result = '<strong>N/A</strong>';
130 1
                break;
131
            default:
132 1
                $result = $value;
133
        }
134
135 1
        return $result;
136
    }
137
138 2
    public function _handler_edit(Request $request, string $handler_id, array &$data, string $component, string $folder = null)
139
    {
140 2
        $data['name'] = $component;
141 2
        if ($handler_id == 'components_configuration_edit_folder') {
142 1
            $data['folder'] = new midcom_db_topic($folder);
143 1
            if ($data['folder']->component != $data['name']) {
144
                throw new midcom_error_notfound("Folder {$folder} not found for configuration.");
145
            }
146 1
            $data['folder']->require_do('midgard:update');
147
148 1
            $data['config'] = $this->_load_configs($data['name'], $data['folder']);
149
        } else {
150 1
            $data['config'] = $this->_load_configs($data['name']);
151
        }
152
153 2
        $schemadb = (new midgard_admin_asgard_schemadb_config($component, $data['config'], isset($folder)))->create();
154 2
        $this->_controller = (new datamanager($schemadb))->get_controller();
155
156 2
        switch ($this->_controller->handle($request)) {
157 2
            case 'save':
158
                if (!$this->save_configuration($data)) {
159
                    midcom::get()->uimessages->add(
160
                        $this->_l10n_midcom->get('component configuration'),
161
                        sprintf($this->_l10n->get('configuration save failed: %s'), midcom_connection::get_error_string()),
162
                        'error'
163
                    );
164
                    // back to edit
165
                    break;
166
                }
167
                midcom::get()->uimessages->add(
168
                    $this->_l10n_midcom->get('component configuration'),
169
                    $this->_l10n->get('configuration saved successfully')
170
                );
171
172
                // FALL-THROUGH (i.e. relocate to view)
173
174 2
            case 'cancel':
175
                if ($handler_id == 'components_configuration_edit_folder') {
176
                    return new midcom_response_relocate($this->router->generate('object_view', ['guid' => $data['folder']->guid]));
177
                }
178
                return new midcom_response_relocate($this->router->generate('components_configuration', ['component' => $data['name']]));
179
        }
180
181 2
        $data['controller'] = $this->_controller;
182
183 2
        if ($handler_id == 'components_configuration_edit_folder') {
184 1
            midgard_admin_asgard_plugin::bind_to_object($data['folder'], $handler_id, $data);
185 1
            $data['view_title'] = sprintf($this->_l10n->get('edit configuration for %s folder %s'), $data['name'], $data['folder']->extra);
186
        } else {
187 1
            $this->_prepare_toolbar(false);
188 1
            $data['view_title'] = sprintf($this->_l10n->get('edit configuration for %s'), $data['name']);
189 1
            $this->_prepare_breadcrumbs();
190 1
            $this->add_breadcrumb(
191 1
                $this->router->generate('components_configuration_edit', ['component' => $this->_request_data['name']]),
192 1
                $this->_l10n_midcom->get('edit')
193
            );
194
        }
195
196 2
        return $this->get_response('midgard_admin_asgard_component_configuration_edit');
197
    }
198
199
    private function save_configuration(array $data) : bool
200
    {
201
        $raw = $this->_controller->get_datamanager()->get_content_raw();
202
        $values = [];
203
204
        foreach ($this->_request_data['config']->get_all() as $key => $val) {
205
            if (!isset($raw[$key]) || $raw[$key] === '') {
206
                continue;
207
            }
208
            $newval = $raw[$key];
209
210
            if (is_array($val)) {
211
                //try make sure entries have the same format before deciding if there was a change
212
                eval("\$newval = $newval;");
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
213
            }
214
215
            if ($newval != $val) {
216
                $values[$key] = $newval;
217
            }
218
        }
219
220
        if ($data['handler_id'] == 'components_configuration_edit_folder') {
221
            // Editing folder configuration
222
            return $this->save_topic($data['folder'], $values);
223
        }
224
        return $this->save_snippet($values);
225
    }
226
227
    /**
228
     * Save configuration values to a topic as "serialized" array
229
     */
230
    private function save_snippet(array $values) : bool
231
    {
232
        $config = var_export($values, true);
233
        // Remove opening and closing array( ) lines, because that's the way midcom likes it
234
        $config = preg_replace('/^.*?\n/', '', $config);
235
        $config = preg_replace('/(\n.*?|\))$/', '', $config);
236
237
        $basedir = midcom::get()->config->get('midcom_sgconfig_basedir');
238
        $sg_snippetdir = new midcom_db_snippetdir();
239
        if (!$sg_snippetdir->get_by_path($basedir)) {
0 ignored issues
show
Bug introduced by
It seems like $basedir can also be of type null; however, parameter $path of midcom_core_dbaobject::get_by_path() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

239
        if (!$sg_snippetdir->get_by_path(/** @scrutinizer ignore-type */ $basedir)) {
Loading history...
240
            // Create config snippetdir
241
            $sg_snippetdir = new midcom_db_snippetdir();
242
            $sg_snippetdir->name = $basedir;
243
            // remove leading slash from name
244
            $sg_snippetdir->name = preg_replace("/^\//", "", $sg_snippetdir->name);
245
            if (!$sg_snippetdir->create()) {
246
                throw new midcom_error("Failed to create snippetdir {$basedir}: " . midcom_connection::get_error_string());
247
            }
248
        }
249
250
        $lib_snippetdir = new midcom_db_snippetdir();
251
        if (!$lib_snippetdir->get_by_path("{$basedir}/{$this->_request_data['name']}")) {
252
            $lib_snippetdir = new midcom_db_snippetdir();
253
            $lib_snippetdir->up = $sg_snippetdir->id;
254
            $lib_snippetdir->name = $this->_request_data['name'];
255
            if (!$lib_snippetdir->create()) {
256
                throw new midcom_error("Failed to create snippetdir {$basedir}/{$lib_snippetdir->name}: " . midcom_connection::get_error_string());
257
            }
258
        }
259
260
        $snippet = new midcom_db_snippet();
261
        if (!$snippet->get_by_path("{$basedir}/{$this->_request_data['name']}/config")) {
262
            $sn = new midcom_db_snippet();
263
            $sn->snippetdir = $lib_snippetdir->id;
264
            $sn->name = 'config';
265
            $sn->code = $config;
266
            return $sn->create();
267
        }
268
269
        $snippet->code = $config;
270
        return $snippet->update();
271
    }
272
273
    /**
274
     * Save configuration values to a topic as parameters
275
     */
276
    private function save_topic(midcom_db_topic $topic, array $config) : bool
277
    {
278
        $success = true;
279
        foreach ($this->_request_data['config']->_global as $global_key => $global_value) {
280
            if (   isset($config[$global_key])
281
                && $config[$global_key] != $global_value) {
282
                continue;
283
                // Skip the ones we will set next
284
            }
285
286
            // Clear unset params
287
            if ($topic->get_parameter($this->_request_data['name'], $global_key)) {
288
                $success = $topic->delete_parameter($this->_request_data['name'], $global_key) && $success;
289
            }
290
        }
291
292
        foreach ($config as $key => $value) {
293
            if (   is_array($value)
294
                || is_object($value)) {
295
                /**
296
                 * See http://trac.midgard-project.org/ticket/1442
297
                 $topic->set_parameter($this->_request_data['name'], var_export($value, true));
298
                 */
299
                continue;
300
            }
301
302
            if ($value === false) {
303
                $value = '0';
304
            }
305
            $success = $topic->set_parameter($this->_request_data['name'], $key, $value) && $success;
306
        }
307
        return $success;
308
    }
309
}
310