Completed
Push — master ( 944c9c...280a9a )
by Antonio Carlos
03:20 queued 10s
created

Hydrator::fixCurrencies()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 1
dl 0
loc 8
ccs 0
cts 4
cp 0
crap 12
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace PragmaRX\Countries\Package\Services;
4
5
use IlluminateAgnostic\Str\Support\Str;
6
use PragmaRX\Coollection\Package\Coollection;
7
8
class Hydrator
9
{
10
    /**
11
     * All hydrators.
12
     *
13
     * @var
14
     */
15
    const HYDRATORS = [
16
        'borders',
17
        'cities',
18
        'collection',
19
        'countries',
20
        'country',
21
        'currencies',
22
        'flag',
23
        'geometry',
24
        'natural_earth_data',
25
        'states',
26
        'taxes',
27
        'timezones',
28
        'timezones_times',
29
        'topology',
30
    ];
31
32
    /**
33
     * Countries repository.
34
     *
35
     * @var Repository
36
     */
37
    protected $repository;
38
39
    /**
40
     * Config.
41
     *
42
     * @var Config
43
     */
44
    protected $config;
45
46
    /**
47
     * Hydrator constructor.
48
     *
49
     * @param object $config
50
     */
51
    public function __construct($config)
52
    {
53
        $this->config = $config;
54
    }
55
56
    /**
57
     * Can hydrate?
58
     *
59
     * @param $element
60
     * @param $enabled
61
     * @param $countryCode
62
     * @return bool
63
     */
64
    protected function canHydrate($element, $enabled, $countryCode)
65
    {
66
        return ($enabled || $this->config->get('hydrate.elements.'.$element)) &&
67
                ! isset($this->repository->countries[$countryCode]['hydrated'][$element]);
68
    }
69
70
    /**
71
     * @param $countryCode
72
     */
73
    protected function createHydrated($countryCode)
74
    {
75
        if (! isset($this->repository->countries[$countryCode]['hydrated'])) {
76
            $this->repository->countries[$countryCode]['hydrated'] = [];
77
        }
78
79
        return $this->repository->countries[$countryCode]['hydrated'];
80
    }
81
82
    protected function fixCurrencies($country)
83
    {
84
        if (! isset($country['currencies']) && isset($country['currency'])) {
85
            $country['currencies'] = $country['currency'];
86
        }
87
88
        return $country;
89
    }
90
91
    /**
92
     * Hydrate elements of a collection of countries.
93
     *
94
     * @param $countries
95
     * @param $elements
96
     * @return mixed
97
     */
98
    private function hydrateCountries($countries, $elements = null)
99
    {
100
        return countriesCollect(
101
            $countries->map(function ($country) use ($elements) {
102
                return $this->hydrateCountry($country, $elements);
103
            })
104
        );
105
    }
106
107
    /**
108
     * Hydrate elements of a country.
109
     *
110
     * @param $country
111
     * @param $elements
112
     * @return mixed
113
     */
114
    private function hydrateCountry($country, $elements)
115
    {
116
        $countryCode = $country['cca3'];
117
118
        $this->addCountry($countryCode, $country);
119
120
        foreach ($elements as $element => $enabled) {
121
            $this->hydrateCountryElement($countryCode, $element, $enabled);
122
        }
123
124
        return $this->getCountry($countryCode);
125
    }
126
127
    /**
128
     * Check if an element is a country.
129
     *
130
     * @param $element
131
     * @return bool
132
     */
133
    private function isCountry($element)
134
    {
135
        return ($element instanceof Coollection || \is_array($element)) && isset($element['cca3']);
136
    }
137
138
    /**
139
     * Check it's a currencies array or code.
140
     *
141
     * @param $data
142
     * @return bool
143
     */
144
    private function isCurrenciesArray($data)
145
    {
146
        return \is_array($data) && isset($data['ISO4217Code']);
147
    }
148
149
    /**
150
     * Load the cities file and merge overloads.
151
     *
152
     * @param $country
153
     * @return mixed
154
     */
155
    private function loadCities($country)
156
    {
157
        return $this->repository->getHelper()->loadJson($country['cca3'], 'cities/default')
158
                ->overwrite($this->repository->getHelper()->loadJson($country['cca3'], 'cities/overload'));
159
    }
160
161
    /**
162
     * Load the states file and merge overloads.
163
     *
164
     * @param $country
165
     * @return mixed
166
     */
167
    private function loadStates($country)
168
    {
169
        return $this->repository->getHelper()->loadJson($country['cca3'], 'states/default')
170
                ->overwrite($this->repository->getHelper()->loadJson($country['cca3'], 'states/overload'));
171
    }
172
173
    /**
174
     * Load the taxes file and merge overloads.
175
     *
176
     * @param $country
177
     * @return mixed
178
     */
179
    private function loadTaxes($country)
180
    {
181
        return $this->repository->getHelper()->loadJson($country['cca3'], 'taxes/default')
182
                                ->overwrite($this->repository->getHelper()->loadJson($country['cca3'], 'taxes/overload'));
183
    }
184
185
    /**
186
     * Check if an element needs hydrated.
187
     *
188
     * @param $countryCode
189
     * @param $element
190
     * @param bool $enabled
191
     * @return bool
192
     */
193
    protected function needsHydration($countryCode, $element, $enabled = false)
194
    {
195
        if (! $this->canHydrate($element, $enabled, $countryCode)) {
196
            return false;
197
        }
198
199
        return $this->updateHydrated($countryCode, $element);
200
    }
201
202
    /**
203
     * Hydrate cities.
204
     *
205
     * @param $country
206
     * @return mixed
207
     */
208
    public function hydrateCities($country)
209
    {
210
        $country['cities'] = $this->loadCities($country);
211
212
        return $country;
213
    }
214
215
    /**
216
     * Hydrate states.
217
     *
218
     * @param $country
219
     * @return mixed
220
     */
221
    public function hydrateStates($country)
222
    {
223
        $country['states'] = $this->loadStates($country);
224
225
        return $country;
226
    }
227
228
    /**
229
     * Hydrate taxes.
230
     *
231
     * @param $country
232
     * @return Coollection
233
     */
234
    public function hydrateTaxes($country)
235
    {
236
        $country['taxes'] = $this->loadTaxes($country);
237
238
        return $country;
239
    }
240
241
    /**
242
     * Hydrate topoloy.
243
     *
244
     * @param $country
245
     * @return mixed
246
     */
247
    public function hydrateTopology($country)
248
    {
249
        $country['topology'] = $this->repository->getTopology($country['cca3']);
250
251
        return $country;
252
    }
253
254
    /**
255
     * Hydrate geometry.
256
     *
257
     * @param $country
258
     * @return mixed
259
     */
260
    public function hydrateGeometry($country)
261
    {
262
        $country['geometry'] = $this->repository->getGeometry($country['cca3']);
263
264
        return $country;
265
    }
266
267
    /**
268
     * Get hydration elements.
269
     *
270
     * @param $elements
271
     * @return array|string|mixed
272
     */
273
    protected function getHydrationElements($elements)
274
    {
275
        $elements = ($elements ?: $this->config->get('hydrate.elements'));
276
277
        if (\is_string($elements) || is_numeric($elements)) {
278
            return [$elements => true];
279
        }
280
281
        return $this->checkHydrationElements($elements);
282
    }
283
284
    /**
285
     * Hydrate flag.
286
     *
287
     * @param $country
288
     * @return mixed
289
     */
290
    public function hydrateFlag($country)
291
    {
292
        $country = countriesCollect($country)->overwrite(
293
            ['flag' => $this->repository->makeAllFlags($country)]
294
        );
295
296
        return $country;
297
    }
298
299
    /**
300
     * Hydrate borders.
301
     *
302
     * @param $country
303
     * @return mixed
304
     */
305
    public function hydrateBorders($country)
306
    {
307
        $country['borders'] = isset($country['borders'])
308
            ? $country['borders'] = countriesCollect($country['borders'])->map(function ($border) {
309
                return $this->repository->call('where', ['cca3', $border])->first();
310
            })
311
            : countriesCollect();
312
313
        return $country;
314
    }
315
316
    /**
317
     * Hydrate timezones.
318
     *
319
     * @param $country
320
     * @return mixed
321
     */
322
    public function hydrateTimezones($country)
323
    {
324
        return $country->overwrite(['timezones' => $this->repository->findTimezones($country['cca3'])]);
325
    }
326
327
    /**
328
     * Hydrate all times for a country timezones.
329
     *
330
     * @param $country
331
     * @return mixed
332
     */
333
    public function hydrateTimezonesTimes($country)
334
    {
335
        $country = $this->hydrateTimezones($country);
336
337
        $country['timezones'] = $country->timezones->map(function ($timezone) {
338
            return $timezone->overwrite(['times' => $this->repository->findTimezoneTime($timezone['zone_id'])]);
339
        });
340
341
        return $country;
342
    }
343
344
    /**
345
     * Hydrate currencies.
346
     *
347
     * @param $country
348
     * @return mixed
349
     */
350
    public function hydrateCurrencies($country)
351
    {
352
        $currencies = [];
353
354
        $country = $this->fixCurrencies($country);
355
356
        if (isset($country['currencies'])) {
357
            $currencies = countriesCollect($country['currencies'])->mapWithKeys(function ($code, $currencyCode) use ($country) {
358
                if ($this->isCurrenciesArray($code)) {
359
                    return [
360
                        $code['ISO4217Code'] => $code,
361
                    ];
362
                }
363
364
                if (is_object($code)) {
365
                    $code = $currencyCode;
366
                }
367
368
                return [
369
                    $code => $this->repository->loadCurrenciesForCountry($code),
370
                ];
371
            });
372
        }
373
374
        $country['currencies'] = $currencies;
375
376
        return $country;
377
    }
378
379
    /**
380
     * Hydrate a countries collection with languages.
381
     *
382
     * @param \PragmaRX\Coollection\Package\Coollection|array|\stdClass $target
383
     * @param null $elements
384
     * @return \PragmaRX\Coollection\Package\Coollection
385
     */
386
    public function hydrate($target, $elements = null)
387
    {
388
        $elements = $this->getHydrationElements($elements);
389
390
        if (coollect($elements)->count() === 0) {
391
            return $target;
392
        }
393
394
        return $this->isCountry($target->toArray())
0 ignored issues
show
Bug introduced by
The method toArray does only exist in PragmaRX\Coollection\Package\Coollection, but not in stdClass.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
395
            ? $this->hydrateCountry($target, $elements)
396
            : $this->hydrateCountries($target, $elements);
397
    }
398
399
    /**
400
     * Get country by country code.
401
     *
402
     * @param $countryCode
403
     * @return mixed
404
     */
405
    public function getCountry($countryCode)
406
    {
407
        return countriesCollect($this->repository->countries[$countryCode]);
408
    }
409
410
    /**
411
     * Check and create a country in the repository.
412
     *
413
     * @param $country
414
     * @param $countryCode
415
     */
416
    public function addCountry($countryCode, $country)
417
    {
418
        if (! isset($this->repository->countries[$countryCode])) {
419
            $this->repository->countries[$countryCode] = $country;
420
        }
421
    }
422
423
    /**
424
     * Hydrate a country element.
425
     *
426
     * @param $countryCode
427
     * @param $element
428
     * @param $enabled
429
     */
430
    public function hydrateCountryElement($countryCode, $element, $enabled)
431
    {
432
        if ($this->needsHydration($countryCode, $element, $enabled)) {
433
            $this->repository->countries[$countryCode] = $this->{'hydrate'.Str::studly($element)}($this->repository->countries[$countryCode]);
434
        }
435
    }
436
437
    /**
438
     * Check hydration elements.
439
     *
440
     * @param $elements
441
     * @return static
442
     */
443
    protected function checkHydrationElements($elements)
444
    {
445
        $elements = countriesCollect($elements)->mapWithKeys(function ($value, $key) {
446
            if (is_numeric($key)) {
447
                $key = $value;
448
                $value = true;
449
            }
450
451
            return [$key => $value];
452
        })->filter(function ($element) {
453
            return $element;
454
        });
455
456
        return $elements;
457
    }
458
459
    /**
460
     * Repository setter.
461
     *
462
     * @param $repository
463
     */
464
    public function setRepository($repository)
465
    {
466
        $this->repository = $repository;
467
    }
468
469
    /**
470
     * Update hydrated.
471
     *
472
     * @param $countryCode
473
     * @param $element
474
     * @return bool
475
     */
476
    protected function updateHydrated($countryCode, $element)
477
    {
478
        $hydrated = $this->createHydrated($countryCode);
479
480
        $hydrated[$element] = true;
481
482
        $this->repository->countries[$countryCode]['hydrated'] = $hydrated;
483
484
        return true;
485
    }
486
}
487