Currencylayer::assignRate()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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