Skip to content

Implement 4 sources of exchange rates, contract and manager #114

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 44 additions & 15 deletions config/currency.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,62 @@
|
*/

'default' => 'USD',
'default' => env('CURRENCY', 'USD'),

/*
|--------------------------------------------------------------------------
| API Key for OpenExchangeRates.org
| Default Currency Rates Source
|--------------------------------------------------------------------------
|
| Only required if you with to use the Open Exchange Rates api. You can
| always just use Yahoo, the current default.
| You could choose a preferred source to get actual exchange rates for
| your currencies list. By default you could use a default free-based source.
|
| Supported: "currencylayer", "exchangeratesapi", "fixer", "openexchangerates"
|
*/

'api_key' => '',
'source' => env('CURRENCY_SOURCE', 'exchangeratesapi'),

/*
|--------------------------------------------------------------------------
| Default Storage Driver
| Sources Configuration
|--------------------------------------------------------------------------
|
| Here you may specify the default storage driver that should be used
| by the framework.
|
| Supported: "database", "filesystem"
| Sources like "fixer", "currencylayer" and "openexchangerates" are required
| to have API token keys. You can always just use "exchangeratesapi" source,
| the default source, but it has limited supported currencies list.
|
*/

'driver' => 'database',
'sources' => [

'fixer' => [
'key' => env('CURRENCY_FIXER_KEY'),
],

'currencylayer' => [
'key' => env('CURRENCY_CURRENCYLAYER_KEY'),
],

'openexchangerates' => [
'key' => env('CURRENCY_OPENEXCHANGERATES_KEY'),
],

],

/*
|--------------------------------------------------------------------------
| Default Storage Driver
|--------------------------------------------------------------------------
|
| Here you may specify the default cache driver that should be used
| Here you may specify the default storage driver that should be used
| by the framework.
|
| Supported: all cache drivers supported by Laravel
| Supported: "database", "filesystem"
|
*/

'cache_driver' => null,
'driver' => env('CURRENCY_DRIVER', 'database'),

/*
|--------------------------------------------------------------------------
Expand All @@ -80,6 +95,20 @@

],

/*
|--------------------------------------------------------------------------
| Default Cache Driver
|--------------------------------------------------------------------------
|
| Here you may specify the default cache driver that should be used
| by the framework.
|
| Supported: all cache drivers supported by Laravel
|
*/

'cache_driver' => env('CURRENCY_CACHE_DRIVER'),

/*
|--------------------------------------------------------------------------
| Currency Formatter
Expand Down Expand Up @@ -113,4 +142,4 @@
],

],
];
];
136 changes: 18 additions & 118 deletions src/Console/Update.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

namespace Torann\Currency\Console;

use DateTime;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
use Torann\Currency\SourceManager;

class Update extends Command
{
Expand All @@ -13,30 +12,31 @@ class Update extends Command
*
* @var string
*/
protected $signature = 'currency:update
{--o|openexchangerates : Get rates from OpenExchangeRates.org}
{--g|google : Get rates from Google Finance}';
protected $signature = 'currency:update {--s|source=}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Update exchange rates from an online source';
protected $description = 'Update exchange rates from the source';

/**
* Currency instance
* The source manager instance.
*
* @var \Torann\Currency\Currency
* @var \Torann\Currency\SourceManager
*/
protected $currency;
protected $manager;

/**
* Create a new command instance.
*
* @param \Torann\Currency\SourceManager $manager
* @return void
*/
public function __construct()
public function __construct(SourceManager $manager)
{
$this->currency = app('currency');
$this->manager = $manager;

parent::__construct();
}
Expand All @@ -58,116 +58,16 @@ public function fire()
*/
public function handle()
{
// Get Settings
$defaultCurrency = $this->currency->config('default');

if ($this->input->getOption('google')) {
// Get rates from google
return $this->updateFromGoogle($defaultCurrency);
}

if ($this->input->getOption('openexchangerates')) {
if (!$api = $this->currency->config('api_key')) {
$this->error('An API key is needed from OpenExchangeRates.org to continue.');

return;
}

// Get rates from OpenExchangeRates
return $this->updateFromOpenExchangeRates($defaultCurrency, $api);
}
}

/**
* Fetch rates from the API
*
* @param $defaultCurrency
* @param $api
*/
private function updateFromOpenExchangeRates($defaultCurrency, $api)
{
$this->info('Updating currency exchange rates from OpenExchangeRates.org...');

// Make request
$content = json_decode($this->request("http://openexchangerates.org/api/latest.json?base={$defaultCurrency}&app_id={$api}&show_alternative=1"));

// Error getting content?
if (isset($content->error)) {
$this->error($content->description);

return;
}

// Parse timestamp for DB
$timestamp = (new DateTime())->setTimestamp($content->timestamp);
$source = $this->option('source') ?: config('currency.source');

// Update each rate
foreach ($content->rates as $code => $value) {
$this->currency->getDriver()->update($code, [
'exchange_rate' => $value,
'updated_at' => $timestamp,
]);
}

$this->currency->clearCache();

$this->info('Update!');
}

/**
* Fetch rates from Google Finance
*
* @param $defaultCurrency
*/
private function updateFromGoogle($defaultCurrency)
{
$this->info('Updating currency exchange rates from finance.google.com...');
foreach ($this->currency->getDriver()->all() as $code => $value) {
// Don't update the default currency, the value is always 1
if ($code === $defaultCurrency) {
continue;
}
$this->info('Updating currency exchange rates...');

$response = $this->request('http://finance.google.com/finance/converter?a=1&from=' . $defaultCurrency . '&to=' . $code);
try {
$this->manager->fetchFrom($source)->update();

if (Str::contains($response, 'bld>')) {
$data = explode('bld>', $response);
$rate = explode($code, $data[1])[0];

$this->currency->getDriver()->update($code, [
'exchange_rate' => $rate,
]);
}
else {
$this->warn('Can\'t update rate for ' . $code);
continue;
}
$this->info('Exchange rates were successfully updated.');
} catch (\Exception $e) {
$this->error($e->getMessage());
}
}

/**
* Make the request to the sever.
*
* @param $url
*
* @return string
*/
private function request($url)
{
$ch = curl_init($url);

curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1");
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 2);
curl_setopt($ch, CURLOPT_MAXCONNECTS, 2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$response = curl_exec($ch);
curl_close($ch);

return $response;
}
}
13 changes: 13 additions & 0 deletions src/Contracts/SourceInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Torann\Currency\Contracts;

interface SourceInterface
{
/**
* Fetch the exchange rates for the default currency.
*
* @return array
*/
public function fetch();
}
83 changes: 83 additions & 0 deletions src/CurrencyRatesUpdater.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace Torann\Currency;

class CurrencyRatesUpdater
{
/**
* The source manager instance.
*
* @var \Torann\Currency\SourceManager
*/
protected $manager;

/**
* The Currency instance.
*
* @var \Torann\Currency\Currency
*/
protected $currency;

/**
* Create a new instance.
*
* @param \Torann\Currency\SourceManager $manager
* @return void
*/
public function __construct(SourceManager $manager)
{
$this->manager = $manager;

$this->currency = app('currency');
}

/**
* Update the exchange rates.
*
* @return void
*/
public function update()
{
foreach ($this->fetchRates() as $code => $currency) {
$this->updateRateFor($code, $currency['rate'], $currency['updated_at']);

$this->clearCache();
}
}

/**
* Fetch the exchange rates.
*
* @return array
*/
protected function fetchRates()
{
return $this->manager->source()->fetch();
}

/**
* Update rate.
*
* @param string $code
* @param mixed $rate
* @param \DateTimeInterface|string $updatedAt
* @return int
*/
protected function updateRateFor($code, $rate, $updatedAt)
{
return $this->currency->getDriver()->update($code, [
'exchange_rate' => $rate,
'updated_at' => $updatedAt,
]);
}

/**
* Clear the currency cache.
*
* @return void
*/
protected function clearCache()
{
$this->currency->clearCache();
}
}
Loading