Passed
Push — master ( 411f74...b3532b )
by Orkhan
01:24
created

CurrencylayerClient::currency()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Orkhanahmadov\Currencylayer;
4
5
use Carbon\CarbonImmutable;
6
use GuzzleHttp\Client as Guzzle;
7
use Orkhanahmadov\Currencylayer\Data\Change;
8
use Orkhanahmadov\Currencylayer\Data\Conversion;
9
use Orkhanahmadov\Currencylayer\Data\Quotes;
10
use Orkhanahmadov\Currencylayer\Data\Timeframe;
11
12
class CurrencylayerClient implements Client
13
{
14
    /**
15
     * @var Guzzle
16
     */
17
    private $client;
18
    /**
19
     * @var string
20
     */
21
    private $accessKey;
22
    /**
23
     * @var string
24
     */
25
    private $source = 'USD';
26
    /**
27
     * @var string
28
     */
29
    private $currencies;
30
    /**
31
     * @var \DateTimeImmutable|null
32
     */
33
    private $date = null;
34
    /**
35
     * @var \DateTimeImmutable|string|null
36
     */
37
    private $startDate = null;
38
    /**
39
     * @var \DateTimeImmutable|string|null
40
     */
41
    private $endDate = null;
42
43
    /**
44
     * CurrencylayerClient constructor.
45
     *
46
     * @param string $accessKey
47
     * @param bool   $useHttps
48
     */
49
    public function __construct(string $accessKey, bool $useHttps = false)
50
    {
51
        $this->client = new Guzzle([
52
            'base_uri' => $useHttps ? 'https://apilayer.net/api/' : 'http://apilayer.net/api/',
53
        ]);
54
55
        $this->accessKey = $accessKey;
56
    }
57
58
    /**
59
     * @param string $source
60
     *
61
     * @return $this
62
     */
63
    public function source(string $source): Client
64
    {
65
        $this->source = $source;
66
67
        return $this;
68
    }
69
70
    /**
71
     * @param array<string>|string $currency
72
     *
73
     * @return $this
74
     */
75
    public function currency($currency): Client
76
    {
77
        if (is_array($currency)) {
78
            $this->currencies = implode(',', $currency);
79
        } else {
80
            $this->currencies = $currency;
81
        }
82
83
        return $this;
84
    }
85
86
    /**
87
     * @param \DateTimeImmutable|string $date
88
     *
89
     * @throws \Exception
90
     *
91
     * @return $this
92
     */
93
    public function date($date): Client
94
    {
95
        $this->date = $date instanceof \DateTimeImmutable ? $date : new CarbonImmutable($date);
96
97
        return $this;
98
    }
99
100
    /**
101
     * @param \DateTimeImmutable|string $date
102
     *
103
     * @throws \Exception
104
     *
105
     * @return $this
106
     */
107
    public function startDate($date): Client
108
    {
109
        $this->startDate = $date instanceof \DateTimeImmutable ? $date : new CarbonImmutable($date);
110
111
        return $this;
112
    }
113
114
    /**
115
     * @param \DateTimeImmutable|string $date
116
     *
117
     * @throws \Exception
118
     *
119
     * @return $this
120
     */
121
    public function endDate($date): Client
122
    {
123
        $this->endDate = $date instanceof \DateTimeImmutable ? $date : new CarbonImmutable($date);
124
125
        return $this;
126
    }
127
128
    /**
129
     * @throws \Exception
130
     *
131
     * @return Quotes
132
     */
133
    public function quotes(): Quotes
134
    {
135
        $query = [
136
            'currencies' => $this->currencies,
137
            'source'     => $this->source,
138
        ];
139
140
        if ($this->date) {
141
            $query['date'] = $this->date->format('Y-m-d');
142
143
            return new Quotes($this->request('historical', $query));
144
        }
145
146
        return new Quotes($this->request('live', $query));
147
    }
148
149
    /**
150
     * @param int|float $amount
151
     *
152
     * @throws \Exception
153
     *
154
     * @return Conversion
155
     */
156
    public function convert($amount): Conversion
157
    {
158
        if (!$this->source || !$this->currencies) {
159
            throw new \InvalidArgumentException('Conversion "from" and "to" currencies were not set.');
160
        }
161
162
        $query = [
163
            'from'   => $this->source,
164
            'to'     => $this->currencies,
165
            'amount' => $amount,
166
        ];
167
168
        if ($this->date) {
169
            $query['date'] = $this->date->format('Y-m-d');
170
        }
171
172
        return new Conversion($this->request('convert', $query));
173
    }
174
175
    /**
176
     * @throws \Exception
177
     *
178
     * @return Timeframe
179
     */
180
    public function timeframe(): Timeframe
181
    {
182
        if (!$this->startDate || !$this->endDate) {
183
            throw new \InvalidArgumentException('Start and/or end dates were not set');
184
        }
185
186
        $data = $this->request('timeframe', [
187
            'source'     => $this->source,
188
            'currencies' => $this->currencies,
189
            'start_date' => $this->startDate->format('Y-m-d'),
190
            'end_date'   => $this->endDate->format('Y-m-d'),
191
        ]);
192
193
        return new Timeframe($data);
194
    }
195
196
    /**
197
     * @throws \Exception
198
     *
199
     * @return Change
200
     */
201
    public function change(): Change
202
    {
203
        if (!$this->startDate || !$this->endDate) {
204
            throw new \InvalidArgumentException('Start and/or end dates were not set');
205
        }
206
207
        $data = $this->request('change', [
208
            'source'     => $this->source,
209
            'currencies' => $this->currencies,
210
            'start_date' => $this->startDate->format('Y-m-d'),
211
            'end_date'   => $this->endDate->format('Y-m-d'),
212
        ]);
213
214
        return new Change($data);
215
    }
216
217
    /**
218
     * @param string $endpoint
219
     * @param array  $query
220
     *
221
     * @return array
222
     */
223
    private function request(string $endpoint, array $query): array
224
    {
225
        $response = $this->client->get($endpoint, [
226
            'query' => array_merge($query, ['access_key' => $this->accessKey]),
227
        ]);
228
229
        $data = \GuzzleHttp\json_decode($response->getBody()->getContents(), true);
230
231
        if (!$data['success']) {
232
            throw new \InvalidArgumentException($data['error']['info']);
233
        }
234
235
        return $data;
236
    }
237
238
    /**
239
     * @param Guzzle $client
240
     */
241
    public function setClient(Guzzle $client): void
242
    {
243
        $this->client = $client;
244
    }
245
}
246