Passed
Push — master ( e0243a...17b35e )
by Orkhan
02:09
created

Currencylayer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
nc 1
nop 1
dl 0
loc 3
c 1
b 0
f 0
cc 1
rs 10
1
<?php
2
3
namespace Orkhanahmadov\LaravelCurrencylayer;
4
5
use Carbon\Carbon;
6
use Illuminate\Support\Arr;
7
use OceanApplications\currencylayer\client;
8
use Orkhanahmadov\LaravelCurrencylayer\Models\Currency;
9
10
class Currencylayer
11
{
12
    /**
13
     * @var client
14
     */
15
    private $client;
16
17
    /**
18
     * Currencylayer constructor.
19
     *
20
     * @param client $client
21
     */
22
    public function __construct(client $client)
23
    {
24
        $this->client = $client;
25
    }
26
27
    /**
28
     * @param Currency|string $source
29
     * @param array<string>|string ...$currencies
30
     *
31
     * @return array<float>|float
32
     */
33
    public function live($source, ...$currencies)
34
    {
35
        $currencies = Arr::flatten($currencies);
36
        if (! $source instanceof Currency) {
37
            $source = Currency::firstOrCreate(['code' => $source]);
38
        }
39
40
        $apiResponse = $this->apiRates($source, $currencies);
41
42
        $rates = $this->createRates($source, $apiResponse['quotes'], $apiResponse['timestamp']);
43
44
        return count($currencies) === 1 ? array_values($rates)[0] : $rates;
45
    }
46
47
    /**
48
     * @param Currency|string $source
49
     * @param Carbon|string $date
50
     * @param array<string>|string ...$currencies
51
     *
52
     * @return array<float>|float
53
     */
54
    public function rate($source, $date, ...$currencies)
55
    {
56
        $currencies = Arr::flatten($currencies);
57
        if (! $source instanceof Currency) {
58
            $source = Currency::firstOrCreate(['code' => $source]);
59
        }
60
        if (! $date instanceof Carbon) {
61
            $date = Carbon::parse($date);
62
        }
63
64
        $apiResponse = $this->apiRates($source, $currencies, $date);
65
66
        $rates = $this->createRates($source, $apiResponse['quotes'], $apiResponse['timestamp']);
67
68
        return count($currencies) === 1 ? array_values($rates)[0] : $rates;
69
    }
70
71
    /**
72
     * @param Currency $source
73
     * @param array<float> $apiRates
74
     * @param int $timestamp
75
     *
76
     * @return array<float>
77
     */
78
    private function createRates(Currency $source, array $apiRates, int $timestamp): array
79
    {
80
        $rates = [];
81
82
        foreach ($apiRates as $code => $rate) {
83
            $target = Currency::firstOrCreate(['code' => $targetCurrencyCode = substr($code, -3)]);
84
85
            $currencyRate = $this->assignRate($source, $target, $rate, $timestamp);
86
87
            $rates[$targetCurrencyCode] = $currencyRate->rate;
88
        }
89
90
        return $rates;
91
    }
92
93
    /**
94
     * @param Currency $source
95
     * @param Currency $target
96
     * @param float $rate
97
     * @param int $timestamp
98
     *
99
     * @return \Illuminate\Database\Eloquent\Model
100
     */
101
    private function assignRate(Currency $source, Currency $target, float $rate, int $timestamp)
102
    {
103
        $currencyRate = $source->rates()->where([
104
            'target_currency_id' => $target->id,
105
            'timestamp' => Carbon::parse($timestamp),
106
        ])->first();
107
108
        if (! $currencyRate) {
109
            $currencyRate = $source->rates()->create([
110
                'target_currency_id' => $target->id,
111
                'rate' => $rate,
112
                'timestamp' => $timestamp,
113
            ]);
114
        }
115
116
        return $currencyRate;
117
    }
118
119
    /**
120
     * @param Currency $source
121
     * @param array<string> $currencies
122
     * @param Carbon|null $date
123
     *
124
     * @return array<mixed>
125
     */
126
    private function apiRates(Currency $source, array $currencies, ?Carbon $date = null): array
127
    {
128
        $client = $this->client->source($source->code)->currencies(implode(',', $currencies));
129
130
        return $date ? $client->date($date->format('Y-m-d'))->historical() : $client->live();
131
    }
132
}
133