Completed
Push — develop ( 7d0f73...48b424 )
by Daniel
12:13 queued 09:25
created

cfg_handler   B

Complexity

Total Complexity 42

Size/Duplication

Total Lines 411
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 42
lcom 1
cbo 2
dl 0
loc 411
ccs 156
cts 156
cp 1
rs 8.295
c 0
b 0
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A get_edit_form() 0 13 2
A get_submitted_settings() 0 15 2
A validate_block_settings() 0 14 2
A get_form() 0 19 1
A decode_source_html() 0 9 2
A generate_config_fields() 0 21 3
A get_field_template() 0 15 1
A get_field_object() 0 21 3
A is_input_field() 0 4 3
A set_legend() 0 14 2
A explain_field() 0 10 3
A append_field() 0 10 2
A set_params() 0 8 2
A get_field_value() 0 4 2
A prep_select_field_for_display() 0 6 1
A prep_checkbox_field_for_display() 0 6 1
A prep_radio_field_for_display() 0 9 2
A prep_multi_select_field_for_display() 0 6 1
A prep_hidden_field_for_display() 0 7 1
A prep_custom_field_for_display() 0 5 2
A get_multi_select() 0 10 3

How to fix   Complexity   

Complex Class

Complex classes like cfg_handler 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 cfg_handler, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 *
4
 * @package sitemaker
5
 * @copyright (c) 2015 Daniel A. (blitze)
6
 * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
7
 *
8
 */
9
10
namespace blitze\sitemaker\services\blocks;
11
12
class cfg_handler extends cfg_fields
13
{
14
	/** @var \phpbb\request\request_interface */
15
	protected $request;
16
17
	/** @var \phpbb\template\template */
18
	protected $template;
19
20
	/** @var \phpbb\language\language */
21
	protected $translator;
22
23
	/** @var \blitze\sitemaker\services\groups */
24
	protected $groups;
25
26
	/** @var string phpBB root path */
27
	protected $phpbb_root_path;
28
29
	/** @var string phpEx */
30
	protected $php_ext;
31
32
	/**
33
	 * Constructor
34
	 *
35
	 * @param \phpbb\request\request_interface		$request				Request object
36
	 * @param \phpbb\template\template				$template				Template object
37
	 * @param \phpbb\language\language				$translator				Language object
38
	 * @param \blitze\sitemaker\services\groups		$groups					Groups object
39
	 * @param string								$phpbb_root_path		phpBB root path
40
	 * @param string								$php_ext				phpEx
41
	 */
42 55
	public function __construct(\phpbb\request\request_interface $request, \phpbb\template\template $template, \phpbb\language\language $translator, \blitze\sitemaker\services\groups $groups, $phpbb_root_path, $php_ext)
43
	{
44 55
		parent::__construct($translator);
45
46 55
		$this->request = $request;
47 55
		$this->template = $template;
48 55
		$this->translator = $translator;
49 55
		$this->groups = $groups;
50 55
		$this->phpbb_root_path = $phpbb_root_path;
51 55
		$this->php_ext = $php_ext;
52 55
	}
53
54
	/**
55
	 * @param array $block_data
56
	 * @param array $default_settings
57
	 * @return string
58
	 */
59 9
	public function get_edit_form(array $block_data, array $default_settings)
60
	{
61
		// @codeCoverageIgnoreStart
62
		if (!function_exists('build_cfg_template'))
63
		{
64
			include($this->phpbb_root_path . 'includes/functions_acp.' . $this->php_ext);
65
		}
66
		// @codeCoverageIgnoreEnd
67
68 9
		$this->generate_config_fields($block_data['settings'], $default_settings);
69
70 9
		return $this->get_form($block_data);
71
	}
72
73
	/**
74
	 * @param array $default_settings
75
	 * @return array|void
76
	 */
77 7
	public function get_submitted_settings(array $default_settings)
78
	{
79 7
		$cfg_array = utf8_normalize_nfc($this->request->variable('config', array('' => ''), true));
80 7
		$cfg_array = $this->decode_source_html($cfg_array);
81 7
		$errors = $this->validate_block_settings($default_settings, $cfg_array);
82
83 7
		if (sizeof($errors))
84 7
		{
85 1
			return array('errors' => join("\n", $errors));
86
		}
87
88 6
		$this->get_multi_select($cfg_array, $default_settings);
89
90 6
		return array_intersect_key($cfg_array, $default_settings);
91
	}
92
93
	/**
94
	 * @param array $default_settings
95
	 * @param array $cfg_array
96
	 * @return array
97
	 */
98 7
	protected function validate_block_settings(array $default_settings, array $cfg_array)
99
	{
100
		// @codeCoverageIgnoreStart
101
		if (!function_exists('validate_config_vars'))
102
		{
103
			include($this->phpbb_root_path . 'includes/functions_acp.' . $this->php_ext);
104
		}
105
		// @codeCoverageIgnoreEnd
106
107 7
		$errors = array();
108 7
		validate_config_vars($default_settings, $cfg_array, $errors);
109
110 7
		return $errors;
111
	}
112
113
	/**
114
	 * As a workaround to prevent mod_security and similar from preventing us from posting html/script,
115
	 * we use encodeURI before submitting data via ajax (see develop/blocks/manager.js).
116
	 * This decodes the data before submitting to the database
117
	 *
118
	 * @param array $cfg_array
119
	 * @return array
120
	 */
121 7
	private function decode_source_html(array $cfg_array)
122
	{
123 7
		if (isset($cfg_array['source']))
124 7
		{
125 1
			$cfg_array['source'] = urldecode($cfg_array['source']);
126 1
		}
127
128 7
		return $cfg_array;
129
	}
130
131
	/**
132
	 * Get the html form
133
	 *
134
	 * @param array $block_data
135
	 * @return string
136
	 */
137 9
	private function get_form(array $block_data)
138
	{
139 9
		$selected_groups = $this->ensure_array($block_data['permission']);
140
141 9
		$this->template->assign_vars(array(
142 9
			'S_ACTIVE'		=> $block_data['status'],
143 9
			'S_TYPE'		=> $block_data['type'],
144 9
			'S_VIEW'		=> $block_data['view'],
145 9
			'S_HIDE_TITLE'	=> $block_data['hide_title'],
146 9
			'S_BLOCK_CLASS'	=> trim($block_data['class']),
147 9
			'S_GROUP_OPS'	=> $this->groups->get_options('all', $selected_groups),
148 9
		));
149
150 9
		$this->template->set_filenames(array(
151 9
			'block_settings' => 'block_settings.html',
152 9
		));
153
154 9
		return $this->template->assign_display('block_settings');
155
	}
156
157
	/**
158
	 * Generate block configuration fields
159
	 *
160
	 * @param array $db_settings
161
	 * @param array $default_settings
162
	 */
163 9
	private function generate_config_fields(array &$db_settings, array $default_settings)
164
	{
165 9
		foreach ($default_settings as $field => $vars)
166
		{
167 8
			if (!$this->is_input_field($field, $vars))
168 8
			{
169 8
				continue;
170
			}
171
172 8
			$db_settings[$field] = $this->get_field_value($field, $vars['default'], $db_settings);
173 8
			$content = $this->get_field_template($field, $db_settings, $vars);
174
175 8
			$this->template->assign_block_vars('options', array(
176 8
				'KEY'			=> $field,
177 8
				'TITLE'			=> $this->translator->lang($vars['lang']),
178 8
				'S_EXPLAIN'		=> $vars['explain'],
179 8
				'TITLE_EXPLAIN'	=> $vars['lang_explain'],
180 8
				'CONTENT'		=> $content,
181 8
			));
182 9
		}
183 9
	}
184
185
	/**
186
	 * Get the field html
187
	 *
188
	 * @param string $field
189
	 * @param array $db_settings
190
	 * @param array $vars
191
	 * @return string
192
	 */
193 8
	private function get_field_template($field, array &$db_settings, array &$vars)
194
	{
195 8
		global $module;
196
197 8
		$vars['lang_explain'] = $this->explain_field($vars);
198 8
		$vars['append'] = $this->append_field($vars);
199
200 8
		$type = explode(':', $vars['type']);
201
202
		// We fake this class as it is needed by the build_cfg_template function
203 8
		$module = new \stdClass();
204 8
		$module->module = $this->get_field_object($vars, $type, $db_settings, $field);
205
206 8
		return build_cfg_template($type, $field, $db_settings, $field, $vars);
207
	}
208
209
	/**
210
	 * @param array $vars
211
	 * @param array $type
212
	 * @param array $db_settings
213
	 * @param string $field
214
	 * @return object
215
	 */
216 8
	private function get_field_object(array &$vars, array &$type, array &$db_settings, $field)
217
	{
218 8
		if (empty($vars['object']))
219 8
		{
220 7
			$object = $this;
221 7
			$method = 'prep_' . $type[0] . '_field_for_display';
222
223 7
			if (is_callable(array($this, $method)))
224 7
			{
225 7
				$this->set_params($field, $vars, $db_settings);
226 7
				$this->$method($vars, $type, $field, $db_settings);
227 7
			}
228 7
		}
229
		else
230
		{
231 1
			$object = $vars['object'];
232 1
			$this->set_params($field, $vars, $db_settings);
233
		}
234
235 8
		return $object;
236
	}
237
238
	/**
239
	 * Set field legend
240
	 *
241
	 * @param string $field
242
	 * @param string|array $vars
243
	 * @return boolean
244
	 */
245 8
	private function is_input_field($field, $vars)
246
	{
247 8
		return ($this->set_legend($field, $vars) || !is_array($vars)) ? false : true;
248
	}
249
250
	/**
251
	 * Set field legend
252
	 *
253
	 * @param string $field
254
	 * @param string|array $vars
255
	 * @return boolean
256
	 */
257 8
	private function set_legend($field, $vars)
258
	{
259 8
		if (strpos($field, 'legend') !== false)
260 8
		{
261 8
			$this->template->assign_block_vars('options', array(
262 8
				'S_LEGEND'	=> $field,
263 8
				'LEGEND'	=> $this->translator->lang($vars)
264 8
			));
265
266 8
			return true;
267
		}
268
269 8
		return false;
270
	}
271
272
	/**
273
	 * Get field details
274
	 *
275
	 * @param array $vars
276
	 * @return mixed|string
277
	 */
278 8
	private function explain_field(array $vars)
279
	{
280 8
		$l_explain = '';
281 8
		if (!empty($vars['explain']))
282 8
		{
283 2
			$l_explain = (isset($vars['lang_explain'])) ? $this->translator->lang($vars['lang_explain']) : $this->translator->lang($vars['lang'] . '_EXPLAIN');
284 2
		}
285
286 8
		return $l_explain;
287
	}
288
289
	/**
290
	 * Add text after field
291
	 *
292
	 * @param array $vars
293
	 * @return mixed|string
294
	 */
295 8
	private function append_field(array $vars)
296
	{
297 8
		$append = '';
298 8
		if (!empty($vars['append']))
299 8
		{
300 1
			$append = $this->translator->lang($vars['append']);
301 1
		}
302
303 8
		return $append;
304
	}
305
306
	/**
307
	 * Set field parameters
308
	 *
309
	 * @param string $field
310
	 * @param array $vars
311
	 * @param array $settings
312
	 */
313 8
	private function set_params($field, array &$vars, array $settings)
314
	{
315 8
		if (isset($vars['options']))
316 8
		{
317 5
			$vars['params'][] = $vars['options'];
318 5
			$vars['params'][] = $settings[$field];
319 5
		}
320 8
	}
321
322
	/**
323
	 * Get field value
324
	 *
325
	 * @param string $field
326
	 * @param mixed $default
327
	 * @param array $db_settings
328
	 * @return mixed
329
	 */
330 8
	private function get_field_value($field, $default, array $db_settings)
331
	{
332 8
		return (isset($db_settings[$field])) ? $db_settings[$field] : $default;
333
	}
334
335
	/**
336
	 * @param array $vars
337
	 * @param array $type
338
	 * @param string $field
339
	 */
340 1
	private function prep_select_field_for_display(array &$vars, array &$type, $field)
341
	{
342 1
		$vars['method'] = 'build_select';
343 1
		$vars['params'][] = $field;
344 1
		$type[0] = 'custom';
345 1
	}
346
347
	/**
348
	 * @param array $vars
349
	 * @param array $type
350
	 * @param string $field
351
	 */
352 2
	private function prep_checkbox_field_for_display(array &$vars, array &$type, $field)
353
	{
354 2
		$vars['method'] = 'build_checkbox';
355 2
		$vars['params'][] = $field;
356 2
		$type[0] = 'custom';
357 2
	}
358
359
	/**
360
	 * @param array $vars
361
	 * @param array $type
362
	 * @param string $field
363
	 */
364 2
	private function prep_radio_field_for_display(array &$vars, array &$type, $field)
365
	{
366 2
		if (!isset($type[1]))
367 2
		{
368 1
			$vars['method'] = 'build_radio';
369 1
			$vars['params'][] = $field;
370 1
			$type[0] = 'custom';
371 1
		}
372 2
	}
373
374
	/**
375
	 * @param array $vars
376
	 * @param array $type
377
	 * @param string $field
378
	 */
379 1
	private function prep_multi_select_field_for_display(array &$vars, array &$type, $field)
380
	{
381 1
		$this->prep_checkbox_field_for_display($vars, $type, $field);
382
383 1
		$vars['method'] ='build_multi_select';
384 1
	}
385
386
	/**
387
	 * @param array $vars
388
	 * @param array $type
389
	 */
390 1
	private function prep_hidden_field_for_display(array &$vars, array &$type)
391
	{
392 1
		$vars['method'] = 'build_hidden';
393 1
		$vars['explain'] = '';
394 1
		$vars['lang'] = '';
395 1
		$type[0] = 'custom';
396 1
	}
397
398
	/**
399
	 * @param array $vars
400
	 * @param array $type
401
	 */
402 1
	private function prep_custom_field_for_display(array &$vars, array &$type)
403
	{
404 1
		$vars['function'] = (!empty($vars['function'])) ? $vars['function'] : '';
405 1
		$type[0] = 'custom';
406 1
	}
407
408
	/**
409
	 * @param array $cfg_array
410
	 * @param array $df_settings
411
	 */
412 6
	private function get_multi_select(array &$cfg_array, array $df_settings)
413
	{
414 6
		$multi_select = $this->request->variable('config', array('' => array(0 => '')), true);
415 6
		$multi_select = array_filter($multi_select);
416
417 6
		foreach ($multi_select as $field => $settings)
418
		{
419 1
			$cfg_array[$field] = (!empty($settings)) ? $settings : $df_settings[$field]['default'];
420 6
		}
421 6
	}
422
}
423