1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author @jayS-de <[email protected]> |
4
|
|
|
* @created: 04.02.15, 17:46 |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
namespace Commercetools\Core\Model\Common; |
8
|
|
|
|
9
|
|
|
use Commercetools\Core\Model\ProductType\AttributeDefinition; |
10
|
|
|
use Commercetools\Core\Model\ProductType\AttributeType; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* @package Commercetools\Core\Model\Common |
14
|
|
|
* @link https://dev.commercetools.com/http-api-projects-products.html#product-variant-attribute |
15
|
|
|
* @method string getName() |
16
|
|
|
* @method getValue() |
17
|
|
|
* @method Attribute setName(string $name = null) |
18
|
|
|
* @method Attribute setValue($value = null) |
19
|
|
|
*/ |
20
|
|
|
class Attribute extends JsonObject |
21
|
|
|
{ |
22
|
|
|
// identifiers for the Api Product Attribute Types: |
23
|
|
|
const T_UNKNOWN = 'unknown'; // zero, should evaluate to false |
24
|
|
|
|
25
|
|
|
const PROP_VALUE = "value"; |
26
|
|
|
const PROP_KEY = "key"; |
27
|
|
|
const PROP_NAME = "name"; |
28
|
|
|
const PROP_CURRENCY_CODE = "currencyCode"; |
29
|
|
|
const PROP_CENT_AMOUNT = "centAmount"; |
30
|
|
|
const PROP_TYPE_ID = "typeId"; |
31
|
|
|
const PROP_ID = "id"; |
32
|
|
|
const PROP_LABEL = "label"; |
33
|
|
|
|
34
|
|
|
const API_BOOL = 'boolean'; |
35
|
|
|
const API_NUMBER = 'number'; |
36
|
|
|
const API_TEXT = 'text'; |
37
|
|
|
const API_LTEXT = 'ltext'; |
38
|
|
|
const API_LENUM = 'lenum'; |
39
|
|
|
const API_ENUM = 'enum'; |
40
|
|
|
const API_MONEY = 'money'; |
41
|
|
|
const API_DATE = 'date'; |
42
|
|
|
const API_TIME = 'time'; |
43
|
|
|
const API_DATETIME = 'datetime'; |
44
|
|
|
const API_SET = 'set'; |
45
|
|
|
const API_NESTED = 'nested'; |
46
|
|
|
const API_REFERENCE = 'reference'; |
47
|
|
|
|
48
|
|
|
protected static $types = []; |
49
|
|
|
|
50
|
26 |
|
public function fieldDefinitions() |
51
|
|
|
{ |
52
|
|
|
return [ |
53
|
26 |
|
static::PROP_NAME => [self::TYPE => 'string'], |
54
|
26 |
|
static::PROP_VALUE => [], |
55
|
|
|
]; |
56
|
|
|
} |
57
|
|
|
|
58
|
26 |
|
public function fieldDefinition($field) |
59
|
|
|
{ |
60
|
26 |
|
if ($field == static::PROP_VALUE) { |
61
|
25 |
|
if (isset(static::$types[$this->getName()])) { |
62
|
18 |
|
$fieldDefinition = static::$types[$this->getName()]; |
63
|
18 |
|
if (!$fieldDefinition instanceof AttributeDefinition) { |
64
|
|
|
return null; |
65
|
|
|
} |
66
|
18 |
|
$fieldType = $fieldDefinition->getType(); |
67
|
18 |
|
if (!$fieldType instanceof AttributeType) { |
68
|
|
|
return null; |
69
|
|
|
} |
70
|
18 |
|
return $fieldType->fieldTypeDefinition(); |
71
|
|
|
} |
72
|
7 |
|
return null; |
73
|
|
|
} |
74
|
26 |
|
return parent::fieldDefinition($field); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @param $attributeName |
79
|
|
|
* @param $value |
80
|
|
|
* @return mixed |
81
|
|
|
*/ |
82
|
18 |
|
protected function getApiType($attributeName, $value) |
83
|
|
|
{ |
84
|
18 |
|
if (isset(static::$types[$attributeName])) { |
85
|
4 |
|
return static::$types[$attributeName]; |
86
|
|
|
} |
87
|
|
|
|
88
|
14 |
|
$apiType = $this->guessApiType($value); |
89
|
14 |
|
$definition = AttributeDefinition::of($this->getContextCallback()); |
90
|
14 |
|
$definition->setName($attributeName); |
91
|
14 |
|
$definition->setType(AttributeType::fromArray(['name' => $apiType])); |
92
|
|
|
|
93
|
14 |
|
if ($apiType == static::API_SET) { |
94
|
2 |
|
$elementType = $this->guessApiType(current($value)); |
95
|
2 |
|
$definition->getType()->setElementType(AttributeType::fromArray(['name' => $elementType])); |
|
|
|
|
96
|
|
|
} |
97
|
14 |
|
$this->setAttributeDefinition($definition); |
98
|
14 |
|
return static::$types[$attributeName]; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* @param AttributeDefinition $definition |
103
|
|
|
* @return $this |
104
|
|
|
*/ |
105
|
18 |
|
public function setAttributeDefinition(AttributeDefinition $definition) |
106
|
|
|
{ |
107
|
18 |
|
static::$types[$definition->getName()] = $definition; |
108
|
|
|
|
109
|
18 |
|
return $this; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @param string $field |
114
|
|
|
*/ |
115
|
19 |
|
protected function initialize($field) |
116
|
|
|
{ |
117
|
19 |
|
if ($field == static::PROP_VALUE) { |
118
|
18 |
|
$name = $this->getRaw(static::PROP_NAME); |
119
|
18 |
|
$value = $this->getRaw(static::PROP_VALUE); |
120
|
18 |
|
$this->getApiType($name, $value); |
121
|
|
|
} |
122
|
19 |
|
parent::initialize($field); |
123
|
19 |
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* @param $value |
127
|
|
|
* @return string |
128
|
|
|
*/ |
129
|
14 |
|
protected function guessApiType($value) |
130
|
|
|
{ |
131
|
|
|
$map = [ |
132
|
14 |
|
'guessUnknown', |
133
|
|
|
'guessBool', |
134
|
|
|
'guessTextLike', |
135
|
|
|
'guessNumber', |
136
|
|
|
'guessEnum', |
137
|
|
|
'guessLocalizedEnum', |
138
|
|
|
'guessMoney', |
139
|
|
|
'guessReference', |
140
|
|
|
'guessLocalizedText', |
141
|
|
|
'guessNested', |
142
|
|
|
'guessSet', |
143
|
|
|
]; |
144
|
|
|
|
145
|
14 |
|
foreach ($map as $function) { |
146
|
14 |
|
if ($type = $this->$function($value)) { |
147
|
14 |
|
return $type; |
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
return static::T_UNKNOWN; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* @param $value |
156
|
|
|
* @param string[] $keys |
157
|
|
|
* @return bool |
158
|
|
|
*/ |
159
|
8 |
|
protected function hasKeys($value, $keys) |
160
|
|
|
{ |
161
|
8 |
|
if (!is_array($value)) { |
162
|
1 |
|
return false; |
163
|
|
|
} |
164
|
8 |
|
$intersect = array_intersect_key(array_flip($keys), $value); |
165
|
8 |
|
return (count($intersect) == count($keys)); |
166
|
|
|
} |
167
|
|
|
|
168
|
14 |
|
protected function guessUnknown($value) |
169
|
|
|
{ |
170
|
14 |
|
return (!isset($value) ? static::T_UNKNOWN : null); |
171
|
|
|
} |
172
|
|
|
|
173
|
12 |
|
protected function guessTextLike($value) |
174
|
|
|
{ |
175
|
12 |
|
return is_string($value) ? static::API_TEXT : null; |
176
|
|
|
} |
177
|
|
|
|
178
|
13 |
|
protected function guessBool($value) |
179
|
|
|
{ |
180
|
13 |
|
return is_bool($value) ? static::API_BOOL : null; |
181
|
|
|
} |
182
|
|
|
|
183
|
10 |
|
protected function guessNumber($value) |
184
|
|
|
{ |
185
|
10 |
|
return is_numeric($value) ? static::API_NUMBER : null; |
186
|
|
|
} |
187
|
|
|
|
188
|
8 |
View Code Duplication |
protected function guessEnum($value) |
|
|
|
|
189
|
|
|
{ |
190
|
8 |
|
if ($this->hasKeys($value, [static::PROP_KEY, static::PROP_LABEL]) && is_string($value[static::PROP_LABEL])) { |
191
|
2 |
|
return static::API_ENUM; |
192
|
|
|
} |
193
|
|
|
|
194
|
7 |
|
return null; |
195
|
|
|
} |
196
|
|
|
|
197
|
7 |
View Code Duplication |
protected function guessLocalizedEnum($value) |
|
|
|
|
198
|
|
|
{ |
199
|
7 |
|
if ($this->hasKeys($value, [static::PROP_KEY, static::PROP_LABEL]) && is_array($value[static::PROP_LABEL])) { |
200
|
1 |
|
return static::API_LENUM; |
201
|
|
|
} |
202
|
|
|
|
203
|
6 |
|
return null; |
204
|
|
|
} |
205
|
|
|
|
206
|
6 |
View Code Duplication |
protected function guessMoney($value) |
|
|
|
|
207
|
|
|
{ |
208
|
6 |
|
if ($this->hasKeys($value, [static::PROP_CENT_AMOUNT, static::PROP_CURRENCY_CODE])) { |
209
|
1 |
|
return static::API_MONEY; |
210
|
|
|
} |
211
|
|
|
|
212
|
5 |
|
return null; |
213
|
|
|
} |
214
|
|
|
|
215
|
5 |
View Code Duplication |
protected function guessReference($value) |
|
|
|
|
216
|
|
|
{ |
217
|
5 |
|
if ($this->hasKeys($value, [static::PROP_TYPE_ID, static::PROP_ID])) { |
218
|
1 |
|
return static::API_REFERENCE; |
219
|
|
|
} |
220
|
|
|
|
221
|
4 |
|
return null; |
222
|
|
|
} |
223
|
|
|
|
224
|
4 |
|
protected function guessLocalizedText($value) |
225
|
|
|
{ |
226
|
4 |
|
if (is_array($value) && !is_numeric(key($value))) { |
227
|
1 |
|
return static::API_LTEXT; |
228
|
|
|
} |
229
|
|
|
|
230
|
3 |
|
return null; |
231
|
|
|
} |
232
|
|
|
|
233
|
2 |
|
protected function guessSet($value) |
234
|
|
|
{ |
235
|
2 |
|
if (is_array($value)) { |
236
|
2 |
|
return static::API_SET; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
return null; |
240
|
|
|
} |
241
|
|
|
|
242
|
3 |
|
protected function guessNested($value) |
243
|
|
|
{ |
244
|
3 |
|
if (is_array($value)) { |
245
|
3 |
|
$first = reset($value); |
246
|
3 |
|
if ($this->hasKeys($first, [static::PROP_NAME, static::PROP_VALUE])) { |
247
|
1 |
|
return static::API_NESTED; |
248
|
|
|
} |
249
|
|
|
} |
250
|
|
|
|
251
|
2 |
|
return null; |
252
|
|
|
} |
253
|
|
|
} |
254
|
|
|
|
If you implement
__call
and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.This is often the case, when
__call
is implemented by a parent class and only the child class knows which methods exist: