Skip to content

Commit 2c07329

Browse files
author
Cédric Girard
committed
Merge pull request #45 from jdambacher/master
Added Yahoo! Finance adapter
2 parents 248bf36 + 4f9a9f5 commit 2c07329

File tree

7 files changed

+180
-5
lines changed

7 files changed

+180
-5
lines changed

Adapter/AdapterFactory.php

+14
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,18 @@ public function createOerAdapter($adapterClass = null)
104104

105105
return $this->create($adapterClass);
106106
}
107+
108+
/**
109+
* Create an YahooCurrencyAdapter.
110+
*
111+
* @return Lexik\Bundle\CurrencyBundle\Adapter\YahooCurrencyAdapter
112+
*/
113+
public function createYahooAdapter($adapterClass = null)
114+
{
115+
if (null == $adapterClass) {
116+
$adapterClass = 'Lexik\Bundle\CurrencyBundle\Adapter\YahooCurrencyAdapter';
117+
}
118+
119+
return $this->create($adapterClass);
120+
}
107121
}

Adapter/YahooCurrencyAdapter.php

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
namespace Lexik\Bundle\CurrencyBundle\Adapter;
4+
5+
use Lexik\Bundle\CurrencyBundle\Exception\CurrencyNotFoundException;
6+
7+
/**
8+
* Yahoo! Adapter
9+
*
10+
* @author Jonas Dambacher <[email protected]>
11+
*/
12+
class YahooCurrencyAdapter extends AbstractCurrencyAdapter
13+
{
14+
/**
15+
* @var string
16+
*/
17+
private $yahooUrl;
18+
19+
/**
20+
* @var array
21+
*/
22+
private $currencyCodes = array();
23+
24+
25+
/**
26+
* Set the Yahoo! url.
27+
*
28+
* @param string $url
29+
*/
30+
public function setYahooUrl($url)
31+
{
32+
$this->yahooUrl = $url;
33+
}
34+
35+
/**
36+
* Init object storage
37+
*/
38+
public function attachAll()
39+
{
40+
foreach ($this->managedCurrencies as $managedCurrency) {
41+
$this->addCurrency($managedCurrency);
42+
}
43+
44+
$defaultRate = 1;
45+
46+
// Add default currency (euro in this example)
47+
$euro = new $this->currencyClass;
48+
$euro->setCode('EUR');
49+
$euro->setRate($defaultRate);
50+
51+
$this[$euro->getCode()] = $euro;
52+
53+
// Build YQL query
54+
$strCodes = '';
55+
foreach ($this->currencyCodes as $index=>$currencyCode) {
56+
$strCodes .= "'EUR".$currencyCode."'";
57+
if ($index != count($this->currencyCodes) - 1) {
58+
$strCodes .= ", ";
59+
}
60+
}
61+
62+
$yqlQuery = "select id,Rate from yahoo.finance.xchange where pair in (".$strCodes.")";
63+
64+
$args = array(
65+
'q' => $yqlQuery,
66+
'format' => "json",
67+
'env' => "store://datatables.org/alltableswithkeys",
68+
);
69+
70+
$yqlQueryURL = $this->yahooUrl
71+
. "?q=" . urlencode($yqlQuery)
72+
. "&format=json"
73+
. "&env=store://datatables.org/alltableswithkeys";
74+
75+
$ch = curl_init();
76+
curl_setopt($ch, CURLOPT_URL, $yqlQueryURL);
77+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
78+
$json = curl_exec($ch);
79+
80+
// Convert JSON response to PHP object
81+
$data = json_decode($json);
82+
$results = $data->query->results->rate;
83+
84+
// Check if query was okay and result is given
85+
if (is_null($results)) {
86+
new \RuntimeException('YQL query failed!');
87+
}
88+
89+
$currencies = array();
90+
91+
foreach ($results as $row) {
92+
$code = substr($row->id, 3);
93+
$rate = $row->Rate;
94+
95+
$currencies[$code] = $rate;
96+
}
97+
98+
foreach ($currencies as $code => $rate) {
99+
if (in_array($code, $this->managedCurrencies)) { // you can check if the currency is in the managed currencies
100+
$currency = new $this->currencyClass;
101+
$currency->setCode($code);
102+
$currency->setRate($rate);
103+
104+
$this[$currency->getCode()] = $currency;
105+
}
106+
}
107+
108+
// get the default rate from the default currency defined in the configuration
109+
if (isset($this[$this->defaultCurrency])) {
110+
$defaultRate = $this[$this->defaultCurrency]->getRate();
111+
}
112+
113+
// convert rates according to the default one.
114+
$this->convertAll($defaultRate);
115+
}
116+
117+
/**
118+
* {@inheritdoc}
119+
*/
120+
public function getIdentifier()
121+
{
122+
return 'yahoo';
123+
}
124+
125+
/**
126+
* Add currency to the query
127+
*
128+
* @param $code
129+
*/
130+
private function addCurrency($code) {
131+
$this->currencyCodes[] = $code;
132+
}
133+
134+
}

DependencyInjection/Configuration.php

+6
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ public function getConfigTreeBuilder()
7373
->scalarNode('oer_app_id')
7474
->defaultValue(null)
7575
->end()
76+
77+
->scalarNode('yahoo_url')
78+
->cannotBeEmpty()
79+
->defaultValue('https://query.yahooapis.com/v1/public/yql')
80+
->end()
81+
7682
->end()
7783
;
7884

DependencyInjection/LexikCurrencyExtension.php

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public function load(array $configs, ContainerBuilder $container)
3030
$container->setParameter('lexik_currency.ecb_url', $config['ecb_url']);
3131
$container->setParameter('lexik_currency.oer_url', $config['oer_url']);
3232
$container->setParameter('lexik_currency.oer_app_id', $config['oer_app_id']);
33+
$container->setParameter('lexik_currency.yahoo_url', $config['yahoo_url']);
3334
$container->setParameter('lexik_currency.decimal_part.precision', $config['decimal_part']['precision']);
3435
$container->setParameter('lexik_currency.decimal_part.round_mode', $config['decimal_part']['round_mode']);
3536

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ lexik_currency:
5656
```
5757
5858
Additonal options (default values are shown here):
59-
59+
6060
```yaml
6161
# app/config/config.yml
6262
lexik_currency:
@@ -137,7 +137,7 @@ You can also pass more arguments, to display or not decimal and the currency sym
137137
If you need to load conversions rates from another source you will have to create a CurrencyAdatpter and set it as the default adapter.
138138

139139
To create your custom adapter you will have to extend `Lexik\Bundle\CurrencyBundle\Adapte\AbstractCurrencyAdapter` which define 2 abstract methods:
140-
* getIdentifier(): returns the identifier of the adapter.
140+
* getIdentifier(): returns the identifier of the adapter.
141141
* attachAll(): loads the currencies with their rate (this method is call from the import command to get all currencies to save in the database).
142142

143143
Here an example
@@ -147,7 +147,7 @@ Here an example
147147

148148
namespace MyProject\With\Some\Rainbows;
149149

150-
use Lexik\Bundle\CurrencyBundle\Adapte\AbstractCurrencyAdapter;
150+
use Lexik\Bundle\CurrencyBundle\Adapter\AbstractCurrencyAdapter;
151151

152152
class RainbowCurrencyAdapter extends AbstractCurrencyAdapter
153153
{
@@ -172,7 +172,7 @@ class RainbowCurrencyAdapter extends AbstractCurrencyAdapter
172172
if (in_array($code, $this->managedCurrencies)) { // you can check if the currency is in the managed currencies
173173
$currency = new $this->currencyClass;
174174
$currency->setCode($code);
175-
$currency->setRate($rate]);
175+
$currency->setRate($rate);
176176

177177
$this[$currency->getCode()] = $currency;
178178
}
@@ -186,7 +186,7 @@ class RainbowCurrencyAdapter extends AbstractCurrencyAdapter
186186
// convert rates according to the default one.
187187
$this->convertAll($defaultRate);
188188
}
189-
189+
190190
/**
191191
* {@inheritdoc}
192192
*/

Resources/config/adapters.xml

+9
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<parameter key="lexik_currency.abstract_adapter.class">Lexik\Bundle\CurrencyBundle\Adapter\AbstractCurrencyAdapter</parameter>
1111
<parameter key="lexik_currency.ecb_adapter.class">Lexik\Bundle\CurrencyBundle\Adapter\EcbCurrencyAdapter</parameter>
1212
<parameter key="lexik_currency.oer_adapter.class">Lexik\Bundle\CurrencyBundle\Adapter\OerCurrencyAdapter</parameter>
13+
<parameter key="lexik_currency.yahoo_adapter.class">Lexik\Bundle\CurrencyBundle\Adapter\YahooCurrencyAdapter</parameter>
1314
<parameter key="lexik_currency.doctrine_adapter.class">Lexik\Bundle\CurrencyBundle\Adapter\DoctrineCurrencyAdapter</parameter>
1415
<parameter key="lexik_currency.doctrine.orm.entity_manager">default</parameter>
1516
</parameters>
@@ -54,6 +55,14 @@
5455
</call>
5556
<tag name="lexik_currency.adapter" alias="oer_currency_adapter" />
5657
</service>
58+
59+
<service id="lexik_currency.yahoo_adapter" class="%lexik_currency.yahoo_adapter.class%" parent="lexik_currency.abstract_adapter">
60+
<factory service="lexik_currency.adapter_factory" method="createYahooAdapter" />
61+
<call method="setYahooUrl">
62+
<argument>%lexik_currency.yahoo_url%</argument>
63+
</call>
64+
<tag name="lexik_currency.adapter" alias="yahoo_currency_adapter" />
65+
</service>
5766
</services>
5867

5968
</container>

Tests/Unit/Adapter/AdapterFactoryTest.php

+11
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ public function testCreateEcbAdapter()
2929
$this->assertEquals(0, count($adapter));
3030
}
3131

32+
public function testCreateYahooAdapter()
33+
{
34+
$factory = new AdapterFactory($this->doctrine, 'EUR', array('EUR', 'USD'), self::CURRENCY_ENTITY);
35+
$adapter = $factory->createYahooAdapter();
36+
37+
$this->assertInstanceOf('Lexik\Bundle\CurrencyBundle\Adapter\YahooCurrencyAdapter', $adapter);
38+
$this->assertEquals('EUR', $adapter->getDefaultCurrency());
39+
$this->assertEquals(array('EUR', 'USD'), $adapter->getManagedCurrencies());
40+
$this->assertEquals(0, count($adapter));
41+
}
42+
3243
public function testCreateDoctrineAdapter()
3344
{
3445
$em = $this->getEntityManager();

0 commit comments

Comments
 (0)