Skip to content

Commit 5ec9575

Browse files
committed
Refactoring and test coverage
1 parent e51ad5d commit 5ec9575

File tree

14 files changed

+336
-280
lines changed

14 files changed

+336
-280
lines changed

examples/example.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
use Otherguy\Currency\DriverFactory;
4+
use Otherguy\Currency\Symbol;
5+
6+
$fixer = DriverFactory::make('fixerio');
7+
$fixer->accessKey('your-access-key-goes-here');
8+
$result = $fixer->from(Symbol::EUR)->get(Symbol::USD);
9+
10+
print_r($result->all());

src/API.php

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/DriverFactory.php

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<?php namespace Otherguy\Currency;
22

3+
use GuzzleHttp\Client as HTTPClient;
4+
use GuzzleHttp\ClientInterface;
35
use Otherguy\Currency\Drivers\CurrencyLayer;
4-
use Otherguy\Currency\Drivers\DriverInterface;
6+
use Otherguy\Currency\Drivers\CurrencyDriverContract;
57
use Otherguy\Currency\Drivers\FixerIo;
6-
use Otherguy\Currency\Drivers\MockDriver;
7-
use Otherguy\Currency\Drivers\OpenExchangeRates;
8+
use Otherguy\Currency\Drivers\MockCurrencyDriver;
89
use Otherguy\Currency\Exceptions\DriverNotFoundException;
910

1011
/**
@@ -14,32 +15,43 @@
1415
*/
1516
class DriverFactory
1617
{
17-
protected const DRIVERS = [
18-
'mock' => MockDriver::class,
19-
'fixerio' => FixerIo::class,
20-
'currencylayer' => CurrencyLayer::class,
21-
'openexchangerates' => OpenExchangeRates::class,
22-
'ratesapi' => RatesApi::class,
23-
'exchangeratesapi' => ExchangeRatesApi::class,
24-
];
18+
protected const DRIVERS = [
19+
'mock' => MockCurrencyDriver::class,
20+
'fixerio' => FixerIo::class,
21+
'currencylayer' => CurrencyLayer::class,
22+
'openexchangerates' => OpenExchangeRates::class,
23+
'ratesapi' => RatesApi::class,
24+
'exchangeratesapi' => ExchangeRatesApi::class,
25+
];
2526

26-
/**
27-
* @param string $name
28-
*
29-
* @return DriverInterface
30-
*
31-
* @throws DriverNotFoundException
32-
*/
33-
public static function make(string $name): DriverInterface
34-
{
35-
$name = strtolower($name);
27+
/**
28+
* @param string $name
29+
* @param ClientInterface|null $client
30+
*
31+
* @return CurrencyDriverContract
32+
*
33+
* @throws DriverNotFoundException
34+
*/
35+
public static function make(string $name, ClientInterface $client = null): CurrencyDriverContract
36+
{
37+
if (!isset(static::DRIVERS[$name])) {
38+
throw new DriverNotFoundException("{$name} is not a valid driver.");
39+
}
3640

37-
if (!isset(static::DRIVERS[$name])) {
38-
throw new DriverNotFoundException("{$name} is not a valid driver.");
39-
}
41+
$class = static::DRIVERS[$name];
4042

41-
$class = static::DRIVERS[$name];
43+
// If no client is specified, create a HTTPClient instance.
44+
$client = $client == null ? new HTTPClient() : $client;
45+
return new $class($client);
46+
}
4247

43-
return new $class;
44-
}
48+
/**
49+
* Get all of the available drivers.
50+
*
51+
* @return array
52+
*/
53+
public static function getDrivers()
54+
{
55+
return array_keys(self::DRIVERS);
56+
}
4557
}
Lines changed: 70 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
<?php namespace Otherguy\Currency\Drivers;
22

33
use DateTime;
4-
use GuzzleHttp\Client as HTTPClient;
4+
use GuzzleHttp\ClientInterface;
55
use GuzzleHttp\Exception\GuzzleException;
6-
use GuzzleHttp\Middleware;
7-
use Otherguy\Currency\Middleware\JsonAwareResponse;
8-
use Psr\Http\Message\ResponseInterface;
6+
use Otherguy\Currency\Exceptions\ApiException;
97

108
/**
119
* Class BaseDriver
1210
*
1311
* @package Otherguy\Currency\Drivers
1412
*/
15-
abstract class BaseDriver implements DriverInterface
13+
abstract class BaseCurrencyDriver implements CurrencyDriverContract
1614
{
1715
protected $apiURL = 'localhost';
1816
protected $protocol = 'http';
19-
protected $accessKey = null;
2017
protected $headers = [
2118
'Accept' => 'application/json',
2219
'Content-Type' => 'application/json',
@@ -28,27 +25,24 @@ abstract class BaseDriver implements DriverInterface
2825
protected $date = null;
2926

3027
protected $httpClient = null;
31-
protected $clientConfig = [
32-
'http_errors' => true,
33-
'timeout' => 30,
34-
'allow_redirects' => true,
35-
'decode_content' => true
36-
];
28+
protected $httpParams = [];
3729

3830
/**
3931
* BaseDriver constructor.
32+
*
33+
* @param ClientInterface $client
4034
*/
41-
public function __construct()
35+
public function __construct(ClientInterface $client)
4236
{
43-
$this->httpClient = $this->makeHttpClient();
37+
$this->httpClient = $client;
4438
}
4539

4640
/**
4741
* @param string $baseCurrency
4842
*
4943
* @return self
5044
*/
51-
public function source(string $baseCurrency): DriverInterface
45+
public function source(string $baseCurrency): CurrencyDriverContract
5246
{
5347
$this->baseCurrency = $baseCurrency;
5448
return $this;
@@ -57,13 +51,13 @@ public function source(string $baseCurrency): DriverInterface
5751
/**
5852
* Alias for 'source'.
5953
*
60-
* @see DriverInterface::source()
61-
*
6254
* @param string $baseCurrency
6355
*
64-
* @return DriverInterface
56+
* @return CurrencyDriverContract
57+
*@see CurrencyDriverContract::source()
58+
*
6559
*/
66-
public function from(string $baseCurrency): DriverInterface
60+
public function from(string $baseCurrency): CurrencyDriverContract
6761
{
6862
return $this->source($baseCurrency);
6963
}
@@ -73,7 +67,7 @@ public function from(string $baseCurrency): DriverInterface
7367
*
7468
* @return self
7569
*/
76-
public function currencies($symbols = []): DriverInterface
70+
public function currencies($symbols = []): CurrencyDriverContract
7771
{
7872
$this->currencies = (array)$symbols;
7973
return $this;
@@ -82,13 +76,13 @@ public function currencies($symbols = []): DriverInterface
8276
/**
8377
* Alias for 'currencies'.
8478
*
85-
* @see DriverInterface::currencies()
86-
*
8779
* @param array $symbols
8880
*
89-
* @return DriverInterface
81+
* @return CurrencyDriverContract
82+
*@see CurrencyDriverContract::currencies()
83+
*
9084
*/
91-
public function to($symbols = []): DriverInterface
85+
public function to($symbols = []): CurrencyDriverContract
9286
{
9387
return $this->currencies($symbols);
9488
}
@@ -98,7 +92,7 @@ public function to($symbols = []): DriverInterface
9892
*
9993
* @return self
10094
*/
101-
public function amount($amount): DriverInterface
95+
public function amount($amount): CurrencyDriverContract
10296
{
10397
$this->amount = $amount;
10498
return $this;
@@ -109,7 +103,7 @@ public function amount($amount): DriverInterface
109103
*
110104
* @return self
111105
*/
112-
public function date($date): DriverInterface
106+
public function date($date): CurrencyDriverContract
113107
{
114108
if (is_integer($date)) {
115109
$this->date = date('Y-m-d', $date);
@@ -121,6 +115,17 @@ public function date($date): DriverInterface
121115

122116
return $this;
123117
}
118+
119+
/**
120+
* Retrieves the date.
121+
*
122+
* @return string
123+
*/
124+
public function getDate(): string
125+
{
126+
return $this->date;
127+
}
128+
124129
/**
125130
* @return array
126131
*/
@@ -140,11 +145,9 @@ public function getBaseCurrency(): string
140145
/**
141146
* @return self
142147
*/
143-
public function secure(): DriverInterface
148+
public function secure(): CurrencyDriverContract
144149
{
145-
$this->protocol = 'https';
146-
$this->httpClient = $this->makeHttpClient();
147-
150+
$this->protocol = 'https';
148151
return $this;
149152
}
150153

@@ -156,64 +159,65 @@ public function getProtocol(): string
156159
return $this->protocol;
157160
}
158161

162+
/**
163+
* Set a config parameter.
164+
*
165+
* @param string $key
166+
* @param string $value
167+
*
168+
* @return self
169+
*/
170+
public function config(string $key, string $value): CurrencyDriverContract
171+
{
172+
$this->httpParams[$key] = $value;
173+
return $this;
174+
}
175+
159176
/**
160177
* Sets the API key to use.
161178
*
162-
* @param string $accessKey Your API key
179+
* Shortcut for config('access_key', $accessKey)
180+
*
181+
* @param string $accessKey Your API key.
163182
*
164183
* @return self
184+
* @see CurrencyDriverContract::config()
185+
*
165186
*/
166-
public function accessKey(string $accessKey): DriverInterface
187+
public function accessKey(string $accessKey): CurrencyDriverContract
167188
{
168-
$this->accessKey = $accessKey;
189+
$this->config('access_key', $accessKey);
169190
return $this;
170191
}
171192

172193
/**
173194
* Performs an HTTP request.
174195
*
175196
* @param string $endpoint The API endpoint.
176-
* @param array $params The URL query parameters.
177197
* @param string $method The HTTP method (defaults to 'GET').
178198
*
179-
* @return array|string|bool The response as decoded JSON.
199+
* @return array|bool The response as decoded JSON.
200+
*
201+
* @throws ApiException
180202
*/
181-
public function apiRequest(string $endpoint, array $params = [], string $method = 'GET')
203+
public function apiRequest(string $endpoint, string $method = 'GET')
182204
{
205+
$url = sprintf('%s://%s/%s', $this->getProtocol(), $this->apiURL, $endpoint);
206+
183207
try {
184-
$response = $this->httpClient
185-
->request($method, $endpoint, [
186-
'query' => array_merge($params, $this->getDefaultParams())
187-
])
188-
->getBody();
208+
$response = $this->httpClient->request($method, $url, ['query' => $this->httpParams])->getBody();
189209
} catch (GuzzleException $e ) {
190-
return false;
210+
throw new ApiException($e->getMessage(), $e->getCode(), $e);
191211
}
192212

193-
return $response;
194-
}
213+
$data = json_decode($response->getContents(), true);
195214

196-
/**
197-
* Creates an instance of HTTPClient
198-
*
199-
* @return HTTPClient
200-
*/
201-
protected function makeHttpClient(): HTTPClient
202-
{
203-
$this->clientConfig['base_uri'] = sprintf('%s://%s', $this->getProtocol(), $this->apiURL);
204-
$client = new HTTPClient($this->clientConfig);
205-
206-
// Push JSON decode middleware on the Guzzle middleware stack
207-
$client->getConfig('handler')->push(Middleware::mapResponse(function (ResponseInterface $response) {
208-
return new JsonAwareResponse(
209-
$response->getStatusCode(),
210-
$response->getHeaders(),
211-
$response->getBody(),
212-
$response->getProtocolVersion(),
213-
$response->getReasonPhrase()
214-
);
215-
}), 'json_decode_middleware');
216-
217-
return $client;
215+
// Check for JSON errors
216+
if( json_last_error() !== JSON_ERROR_NONE ) {
217+
throw new ApiException(json_last_error_msg(), json_last_error());
218+
}
219+
220+
// Otherwise return data.
221+
return $data;
218222
}
219223
}

0 commit comments

Comments
 (0)