ConfigHelper::toArray()   C
last analyzed

Complexity

Conditions 13
Paths 15

Size

Total Lines 44
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 13

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 44
ccs 20
cts 20
cp 1
rs 6.6166
c 0
b 0
f 0
cc 13
nc 15
nop 3
crap 13

How to fix   Complexity   

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
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) The s9e authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Configurator\Helpers;
9
10
use RuntimeException;
11
use s9e\TextFormatter\Configurator\ConfigProvider;
12
use s9e\TextFormatter\Configurator\FilterableConfigValue;
13
use s9e\TextFormatter\Configurator\JavaScript\Dictionary;
14
use Traversable;
15
16
abstract class ConfigHelper
17
{
18
	/**
19
	* Recursively filter a config array to replace variants with the desired value
20
	*
21
	* @param  array  $config Config array
22
	* @param  string $target Target parser
23
	* @return array          Filtered config
24
	*/
25 6
	public static function filterConfig(array $config, $target = 'PHP')
26
	{
27 6
		$filteredConfig = [];
28 6
		foreach ($config as $name => $value)
29
		{
30 6
			if ($value instanceof FilterableConfigValue)
31
			{
32 6
				$value = $value->filterConfig($target);
33 6
				if (!isset($value))
34
				{
35 2
					continue;
36
				}
37
			}
38 6
			if (is_array($value))
39
			{
40 3
				$value = self::filterConfig($value, $target);
41
			}
42 6
			$filteredConfig[$name] = $value;
43
		}
44
45 6
		return $filteredConfig;
46
	}
47
48
	/**
49
	* Generate a quickMatch string from a list of strings
50
	*
51
	* This is basically a LCS implementation, tuned for small strings and fast failure
52
	*
53
	* @param  array $strings Array of strings
54
	* @return mixed          quickMatch string, or FALSE if none could be generated
55
	*/
56 4
	public static function generateQuickMatchFromList(array $strings)
57
	{
58 4
		foreach ($strings as $string)
59
		{
60 4
			$stringLen  = strlen($string);
61 4
			$substrings = [];
62
63 4
			for ($len = $stringLen; $len; --$len)
64
			{
65 4
				$pos = $stringLen - $len;
66
67
				do
68
				{
69 4
					$substrings[substr($string, $pos, $len)] = 1;
70
				}
71 4
				while (--$pos >= 0);
72
			}
73
74 4
			if (isset($goodStrings))
75
			{
76 4
				$goodStrings = array_intersect_key($goodStrings, $substrings);
77
78 4
				if (empty($goodStrings))
79
				{
80 4
					break;
81
				}
82
			}
83
			else
84
			{
85 4
				$goodStrings = $substrings;
86
			}
87
		}
88
89 4
		if (empty($goodStrings))
90
		{
91 1
			return false;
92
		}
93
94
		// The strings are stored by length descending, so we return the first in the list
95 3
		return strval(key($goodStrings));
96
	}
97
98
	/**
99
	* Optimize the size of a deep array by deduplicating identical structures
100
	*
101
	* This method is meant to be used on a config array which is only read and never modified
102
	*
103
	* @param  array &$config
104
	* @param  array &$cache
105
	* @return array
106
	*/
107 1
	public static function optimizeArray(array &$config, array &$cache = [])
108
	{
109 1
		foreach ($config as $k => &$v)
110
		{
111 1
			if (!is_array($v))
112
			{
113 1
				continue;
114
			}
115
116
			// Dig deeper into this array
117 1
			self::optimizeArray($v, $cache);
118
119
			// Look for a matching structure
120 1
			$cacheKey = serialize($v);
121 1
			if (!isset($cache[$cacheKey]))
122
			{
123
				// Record this value in the cache
124 1
				$cache[$cacheKey] = $v;
125
			}
126
127
			// Replace the entry in $config with a reference to the cached value
128 1
			$config[$k] =& $cache[$cacheKey];
129
		}
130 1
		unset($v);
131
	}
132
133
	/**
134
	* Convert a structure to a (possibly multidimensional) array
135
	*
136
	* @param  mixed $value
137
	* @param  bool  $keepEmpty Whether to keep empty arrays instead of removing them
138
	* @param  bool  $keepNull  Whether to keep NULL values instead of removing them
139
	* @return array
140
	*/
141 11
	public static function toArray($value, $keepEmpty = false, $keepNull = false)
142
	{
143 11
		$array = [];
144
145 11
		foreach ($value as $k => $v)
146
		{
147 11
			$isDictionary = $v instanceof Dictionary;
148 11
			if ($v instanceof ConfigProvider)
149
			{
150 3
				$v = $v->asConfig();
151
			}
152 11
			elseif ($v instanceof Traversable || is_array($v))
153
			{
154 9
				$v = self::toArray($v, $keepEmpty, $keepNull);
155
			}
156 9
			elseif (is_scalar($v) || is_null($v))
157 8
			{
158
				// Do nothing
159
			}
160
			else
161
			{
162 1
				$type = (is_object($v))
163 1
				      ? 'an instance of ' . get_class($v)
164 1
				      : 'a ' . gettype($v);
165
166 1
				throw new RuntimeException('Cannot convert ' . $type . ' to array');
167
			}
168
169 10
			if (!isset($v) && !$keepNull)
170
			{
171
				// We don't record NULL values
172 3
				continue;
173
			}
174
175 10
			if (!$keepEmpty && $v === [])
176
			{
177
				// We don't record empty structures
178 2
				continue;
179
			}
180
181 10
			$array[$k] = ($isDictionary) ? new Dictionary($v) : $v;
182
		}
183
184 10
		return $array;
185
	}
186
}