Passed
Push — master ( cd1865...3b0c7b )
by Aimeos
04:41
created

Traits::setConfigFlat()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
c 0
b 0
f 0
dl 0
loc 13
rs 10
cc 3
nc 4
nop 1
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2018-2025
6
 * @package MShop
7
 * @subpackage Common
8
 */
9
10
11
namespace Aimeos\MShop\Common\Item\Config;
12
13
14
/**
15
 * Common trait for items containing configurations
16
 *
17
 * @package MShop
18
 * @subpackage Common
19
 */
20
trait Traits
21
{
22
	/**
23
	 * Returns the configuration values of the item
24
	 *
25
	 * @return array Configuration values
26
	 */
27
	abstract public function getConfig() : array;
28
29
30
	/**
31
	 * Sets the configuration values of the item
32
	 *
33
	 * @param array $config Configuration values
34
	 * @return \Aimeos\MShop\Common\Item\Iface Item for chaining method calls
35
	 */
36
	abstract public function setConfig( array $config ) : \Aimeos\MShop\Common\Item\Iface;
37
38
39
	/**
40
	 * Returns the configuration value for the specified path
41
	 *
42
	 * @param string $key Key of the associative array or path to value like "path/to/value"
43
	 * @param mixed $default Default value if no configration is found
44
	 * @return mixed Configuration value or array of values
45
	 */
46
	public function getConfigValue( string $key, $default = null )
47
	{
48
		return $this->getArrayValue( $this->getConfig(), explode( '/', trim( $key, '/' ) ), $default );
49
	}
50
51
52
	/**
53
	 * Sets all configuration values at once
54
	 *
55
	 * @param array $flat Associative list of keys (with "/" for nested arrays) and values
56
	 * @return \Aimeos\MShop\Common\Item\Iface Item for chaining method calls
57
	 */
58
	public function setConfigFlat( array $flat ) : \Aimeos\MShop\Common\Item\Iface
59
	{
60
		$config = [];
61
62
		foreach( $flat as $key => $value ) {
63
			$config = $this->setArrayValue( $config, explode( '/', trim( $key, '/' ) ), $value );
64
		}
65
66
		if( !$this->compareConfig( $this->getConfig(), $config ) ) {
67
			return $this->setConfig( $config );
68
		}
69
70
		return $this;
71
	}
72
73
74
	/**
75
	 * Sets the configuration value for the specified path
76
	 *
77
	 *  Setting "value" by using "path/to" as key would result in:
78
	 *  [
79
	 *    'path' => [
80
	 *      'to' => 'value'
81
	 *    ]
82
	 *  ]
83
	 *
84
	 * @param string $key Key of the associative array or path to value like "path/to/value"
85
	 * @param mixed $value Value to set for the key
86
	 * @return \Aimeos\MShop\Common\Item\Iface Item for chaining method calls
87
	 */
88
	public function setConfigValue( string $key, $value ) : \Aimeos\MShop\Common\Item\Iface
89
	{
90
		return $this->setConfig( $this->setArrayValue( $this->getConfig(), explode( '/', trim( $key, '/' ) ), $value ) );
91
	}
92
93
94
	/**
95
	 * Returns if two associative arrays with string keys are equal
96
	 *
97
	 * @param array $a First associative array
98
	 * @param array $b Second associative array
99
	 * @return bool TRUE if arrays are loosly equal, FALSE if there are differences other than the order of keys
100
	 */
101
	protected function compareConfig( array $a, array $b ) : bool
102
	{
103
		if( count( $a ) !== count( $b ) || array_diff_key( $a, $b ) ) {
104
			return false;
105
		}
106
107
		foreach( $a as $k => $v )
108
		{
109
			$bv = $b[$k];
110
111
			if( is_array( $v ) && is_array( $bv ) )
112
			{
113
				if( !$this->compareConfig( $v, $bv ) ) {
114
					return false;
115
				}
116
			}
117
			elseif( $v != $bv )
118
			{
119
				return false;
120
			}
121
		}
122
123
		return true;
124
	}
125
126
127
	/**
128
	 * Returns a configuration value from an array
129
	 *
130
	 * @param array $config The array to search in
131
	 * @param array $parts Configuration path parts to look for inside the array
132
	 * @param mixed $default Default value if no configuration is found
133
	 * @return mixed Found value or null if no value is available
134
	 */
135
	protected function getArrayValue( array $config, array $parts, $default )
136
	{
137
		if( ( $current = array_shift( $parts ) ) !== null && isset( $config[$current] ) )
138
		{
139
			if( count( $parts ) > 0 )
140
			{
141
				if( is_array( $config[$current] ) ) {
142
					return $this->getArrayValue( $config[$current], $parts, $default );
143
				}
144
145
				return $default;
146
			}
147
148
			return $config[$current];
149
		}
150
151
		return $default;
152
	}
153
154
155
	/**
156
	 * Sets the value for the given key parts in the array configuration
157
	 *
158
	 * @param array $config The configuration array to set the key/value pair in
159
	 * @param array $parts Configuration path parts to use in the array
160
	 * @param mixed $value Value to set in the configuration array
161
	 * @return array Modified configuration array
162
	 */
163
	protected function setArrayValue( array $config, array $parts, $value ) : array
164
	{
165
		$current = array_shift( $parts );
166
167
		if( !empty( $parts ) ) {
168
			$config[$current] = $this->setArrayValue( $config[$current] ?? [], $parts, $value );
169
		} else {
170
			$config[$current] = $value;
171
		}
172
173
		return $config;
174
	}
175
}
176