Field::setValueRangeAutodetect()   B
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 12
cts 12
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 10
nc 5
nop 1
crap 5
1
<?php
2
3
namespace Radowoj\Yaah;
4
5
use InvalidArgumentException;
6
7
/**
8
 * Class representation of WebAPI auction field
9
 * @see http://allegro.pl/webapi/documentation.php/show/id,113
10
 */
11
class Field
12
{
13
    const DATE_REGEX = '/^\d{2}\-\d{2}\-\d{4}$/';
14
15
    const VALUE_STRING = 'fvalueString';
16
    const VALUE_INT = 'fvalueInt';
17
    const VALUE_FLOAT = 'fvalueFloat';
18
    const VALUE_IMAGE = 'fvalueImage';
19
    const VALUE_DATETIME = 'fvalueDatetime';
20
    const VALUE_DATE = 'fvalueDate';
21
    const VALUE_RANGE_INT = 'fvalueRangeInt';
22
    const VALUE_RANGE_FLOAT = 'fvalueRangeFloat';
23
    const VALUE_RANGE_DATE = 'fvalueRangeDate';
24
25
    const DEFAULT_STRING = '';
26
    const DEFAULT_INT = 0;
27
    const DEFAULT_FLOAT = 0;
28
    const DEFAULT_IMAGE = '';
29
    const DEFAULT_DATETIME = 0;
30
    const DEFAULT_DATE = '';
31
32
    /**
33
     * Allegro WebAPI fid
34
     * @var integer
35
     */
36
    protected $fid = null;
37
38
39
    /**
40
     * array of fValues of this Field
41
     * @var array
42
     */
43
    protected $fValues = [];
44
45
46
    /**
47
     * @param integer $fid WebAPI fid for given field
48
     * @param mixed $value value for given field
49
     * @param string $forceValueType value type to force (i.e. fvalueImage)
50
     */
51 30
    public function __construct($fid = 0, $value = null, $forceValueType = '')
52
    {
53 30
        $this->setFid($fid);
54 29
        $this->fValues = $this->getDefaults();
55
56
        //null value should result in field with default values
57 29
        if (is_null($value)) {
58 8
            return;
59
        }
60
61
        //if value type was specified (useful for fvalueImage, fvalueDatetime etc.)
62 21
        if ($forceValueType) {
63 3
            $this->setValueForced($forceValueType, $value);
64 2
            return;
65
        }
66
67
        //if no forced value type is given, autodetect it
68 19
        $this->setValueAutodetect($value);
69 17
    }
70
71
72
    /**
73
     * Default values, "empty" WebAPI fields item
74
     * @return array
75
     */
76 29
    protected function getDefaults()
77
    {
78
        return [
79 29
            self::VALUE_STRING => self::DEFAULT_STRING,
80 29
            self::VALUE_INT => self::DEFAULT_INT,
81 29
            self::VALUE_FLOAT => self::DEFAULT_FLOAT,
82 29
            self::VALUE_IMAGE => self::DEFAULT_IMAGE,
83 29
            self::VALUE_DATETIME => self::DEFAULT_DATETIME,
84 29
            self::VALUE_DATE => self::DEFAULT_DATE,
85 29
            self::VALUE_RANGE_INT => [
86 29
                self::VALUE_RANGE_INT . 'Min' => self::DEFAULT_INT,
87 29
                self::VALUE_RANGE_INT . 'Max' => self::DEFAULT_INT,
88 29
            ],
89 29
            self::VALUE_RANGE_FLOAT => [
90 29
                self::VALUE_RANGE_FLOAT . 'Min' => self::DEFAULT_FLOAT,
91 29
                self::VALUE_RANGE_FLOAT . 'Max' => self::DEFAULT_FLOAT,
92 29
            ],
93 29
            self::VALUE_RANGE_DATE => [
94 29
                self::VALUE_RANGE_DATE . 'Min' => self::DEFAULT_DATE,
95 29
                self::VALUE_RANGE_DATE . 'Max' => self::DEFAULT_DATE,
96 29
            ],
97 29
        ];
98
    }
99
100
101
    /**
102
     * Set fid of this Field
103
     * @param integer $fid
104
     */
105 30
    public function setFid($fid)
106
    {
107 30
        if (!is_integer($fid)) {
108 1
            throw new InvalidArgumentException('fid must be an integer, ' . gettype($fid) . ' given');
109
        }
110 29
        $this->fid = $fid;
111 29
    }
112
113
114
    /**
115
     * Set value to fValue index of corresponding type
116
     * @param mixed $value
117
     */
118 19
    protected function setValueAutodetect($value)
119
    {
120 19
        if (is_integer($value)) {
121 4
            $this->fValues[self::VALUE_INT] = $value;
122 19
        } elseif (is_float($value)) {
123 4
            $this->fValues[self::VALUE_FLOAT] = $value;
124 18
        } elseif (is_string($value)) {
125 9
            $this->setValueStringAutodetect($value);
126 17
        } elseif (is_array($value)) {
127 7
            $this->setValueRangeAutodetect($value);
128 6
        } else {
129 1
            throw new InvalidArgumentException('Not supported value type: ' . gettype($value) . "; fid={$this->fid}");
130
        }
131 17
    }
132
133
134
    /**
135
     * Detect type of string value (date or normal string)
136
     * @param string $value value to detect type
137
     */
138 9
    protected function setValueStringAutodetect($value)
139
    {
140 9
        if (preg_match(self::DATE_REGEX, $value)) {
141 4
            $this->fValues[self::VALUE_DATE] = $value;
142 4
        } else {
143 8
            $this->fValues[self::VALUE_STRING] = $value;
144
        }
145 9
    }
146
147
148
    /**
149
     * Detect type of range passed as argument (int, float, date)
150
     * @param array $range range to detect type of
151
     */
152 7
    protected function setValueRangeAutodetect(array $range)
153
    {
154 7
        if (count($range) !== 2) {
155 1
            throw new InvalidArgumentException('Range array must have exactly 2 elements');
156
        }
157
158
        //make sure array has numeric keys
159 6
        $range = array_values($range);
160
161 6
        if ($this->isRangeFloat($range)) {
162 2
            $this->setRangeFloat($range);
163 6
        } elseif ($this->isRangeInt($range)) {
164 2
            $this->setRangeInt($range);
165 4
        } elseif ($this->isRangeDate($range)) {
166 2
            $this->setRangeDate($range);
167 2
        }
168 6
    }
169
170
171
    /**
172
     * Sets float range values from given array
173
     * @param array $range array of two float values
174
     */
175 2
    protected function setRangeFloat(array $range)
176
    {
177 2
        asort($range);
178 2
        $this->fValues[self::VALUE_RANGE_FLOAT] = array_combine(
179 2
            ['fvalueRangeFloatMin', 'fvalueRangeFloatMax'],
180
            $range
181 2
        );
182 2
    }
183
184
185
    /**
186
     * Sets int range values from given array
187
     * @param array $range array of two int values
188
     */
189 2
    protected function setRangeInt(array $range)
190
    {
191 2
        asort($range);
192 2
        $this->fValues[self::VALUE_RANGE_INT] = array_combine(
193 2
            ['fvalueRangeIntMin', 'fvalueRangeIntMax'],
194
            $range
195 2
        );
196 2
    }
197
198
199
    /**
200
     * Sets date range values from given array
201
     * @param array $range array of two date values
202
     */
203 2
    protected function setRangeDate(array $range)
204
    {
205
        usort($range, function($date1, $date2){
206 2
            return strtotime($date1) - strtotime($date2);
207 2
        });
208 2
        $this->fValues[self::VALUE_RANGE_DATE] = array_combine(
209 2
            ['fvalueRangeDateMin', 'fvalueRangeDateMax'],
210
            $range
211 2
        );
212 2
    }
213
214
215
    /**
216
     * Checks if given range is float
217
     * @param  array   $range range to check
218
     * @return boolean
219
     */
220 6
    protected function isRangeFloat(array $range)
221
    {
222 6
        $floats = array_filter($range, 'is_float');
223 6
        return (count($floats) == 2);
224
    }
225
226
227
    /**
228
     * Checks if given range is int
229
     * @param  array   $range range to check
230
     * @return boolean
231
     */
232 4
    protected function isRangeInt(array $range)
233
    {
234 4
        $ints = array_filter($range, 'is_int');
235 4
        return (count($ints) == 2);
236
    }
237
238
239
    /**
240
     * Checks if given range is date
241
     * @param  array   $range range to check
242
     * @return boolean
243
     */
244
    public function isRangeDate(array $range)
245
    {
246 2
        $dates = array_filter($range, function($item){
247 2
            return preg_match(self::DATE_REGEX, $item);
248 2
        });
249
250 2
        return (count($dates) == 2);
251
    }
252
253
254
    /**
255
     * Set value of arbitrary type
256
     * @param string $forceValueType type ('fvalueString', 'fvalueInt', ...)
257
     * @param mixed $value to set
258
     */
259 3
    protected function setValueForced($forceValueType, $value)
260
    {
261 3
        if (!array_key_exists($forceValueType, $this->fValues)) {
262 1
            throw new InvalidArgumentException("Class " . get_class($this) . " does not have property: {$forceValueType}");
263
        }
264
265 2
        $this->fValues[$forceValueType] = $value;
266 2
    }
267
268
269
    /**
270
     * Returns WebAPI representation of Field
271
     * @return array field
272
     */
273 17
    public function toArray()
274
    {
275 17
        $this->fValues['fid'] = $this->fid;
276 17
        return $this->fValues;
277
    }
278
279
280
    /**
281
     * Creates object from WebAPI representation of Field
282
     */
283 8
    public function fromArray(array $array)
284
    {
285
        //recursive object to array :)
286 8
        $array = json_decode(json_encode($array), true);
287
288 8
        if (!array_key_exists('fid', $array)) {
289 1
            throw new InvalidArgumentException('Fid is required');
290
        }
291
292 7
        $this->setFid($array['fid']);
293 7
        unset($array['fid']);
294
295 7
        foreach ($array as $key => $value) {
296 7
            if (!array_key_exists($key, $this->fValues)) {
297 1
                throw new InvalidArgumentException("Unknown Field property: {$key}");
298
            }
299
300 7
            $this->fValues[$key] = $value;
301 7
        }
302 6
    }
303
304
305
    /**
306
     * Return field fid
307
     * @return integer
308
     */
309 6
    public function getFid()
310
    {
311 6
        return $this->fid;
312
    }
313
314
315
    /**
316
     * Return first property that is different from its default value
317
     * @return mixed | null
318
     */
319 17
    public function getValue()
320
    {
321 17
        $defaults = $this->getDefaults();
322 17
        foreach ($this->fValues as $key => $fValue) {
323 17
            if ($fValue !== $defaults[$key]) {
324 16
                return is_array($fValue) ? array_values($fValue) : $fValue;
325
            }
326 15
        }
327
328
        //if all values are at defaults, we're unable to determine
329
        //which one was set without additional business logic involving
330
        //fids - especially if the defaults come from WebAPI (fromArray())
331 1
        return null;
332
    }
333
334
335
}
336