Skip to content

Commit b2bce2c

Browse files
authored
Currencies Update (#10)
Currencies Update
2 parents 10a78c8 + 04404d6 commit b2bce2c

14 files changed

+1633
-48
lines changed

README.md

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,11 @@ In order to get a specific currency:
277277
use PostScripton\Money\Currency;
278278

279279
$usd = Currency::code('USD');
280+
$usd = Currency::code('usd');
281+
$usd = Currency::code('840');
280282
```
281283

282-
❗ Only international codes such as USD”, “EUR”, “RUB and so on should be used as a code.
284+
❗ Only international codes such as USD / 840, EUR / 978, RUB / 643 and so on should be used as a code.
283285

284286
---
285287

@@ -291,9 +293,28 @@ You can also get or change some data from Currency object:
291293
use PostScripton\Money\Currency;
292294

293295
$usd = Currency::code('USD');
294-
$usd->getCode(); // USD
296+
297+
$usd->getFullName(); // "United States dollar"
298+
$usd->getName(); // "dollar"
299+
$usd->getCode(); // "USD"
300+
$usd->getNumCode(); // "840"
295301
$usd->getSymbol(); // "$"
296302
$usd->getPosition(); // 0 (Currency::POS_START)
303+
$usd->getDisplay(); // 10 (Currency::DISPLAY_SYMBOL)
304+
```
305+
306+
`getSymbol()` takes an index as first parameter only if there are more than one symbol for the currency.
307+
308+
```php
309+
use PostScripton\Money\Currency;
310+
311+
Currency::setCurrencyList(Currency::LIST_ALL);
312+
313+
$currency = Currency::code('EGP');
314+
315+
// ['£', 'ج.م']
316+
$currency->getSymbol(); // '£'
317+
$currency->getSymbol(1); // 'ج.م'
297318
```
298319

299320
---
@@ -319,6 +340,49 @@ $money->toString(); // "123.4 $"
319340

320341
---
321342

343+
#### Display
344+
You may specify the way to display the currency whether it will be as an iso-code or a symbol.
345+
Use following constants:
346+
347+
```php
348+
use PostScripton\Money\Currency;
349+
use PostScripton\Money\Money;
350+
351+
$money = new Money(1234);
352+
353+
$money->settings->getCurrency()->getDisplay(); // 10 (Currency::DISPLAY_SYMBOL)
354+
$money->toString(); // "$ 123.4"
355+
356+
$money->settings->getCurrency()->setDisplay(Currency::DISPLAY_CODE);
357+
358+
$money->settings->getCurrency()->getDisplay(); // 11 (Currency::DISPLAY_CODE)
359+
$money->toString(); // "USD 123.4"
360+
361+
// If you don't like the look of the code at the beginning
362+
$money->settings->getCurrency()->setPosition(Currency::POS_END);
363+
$money->toString(); // "123.4 USD"
364+
```
365+
366+
---
367+
368+
#### Currency List
369+
If you wish, you may select another currency list.
370+
To select currency list by default, go to the `config/money.php` and find there `currency_list`.
371+
372+
All the lists are located at `vendor/postscripton/money/src/List`, so if you want, you can check something up there.
373+
374+
```php
375+
use PostScripton\Money\Currency;
376+
377+
Currency::setCurrencyList(Currency::LIST_POPULAR);
378+
Currency::code('USD');
379+
380+
Currency::setCurrencyList(Currency::LIST_ALL);
381+
Currency::code('EGP');
382+
```
383+
384+
---
385+
322386
### 💵 Money
323387
Here we are, prepared and ready to create our own Money objects.
324388

@@ -541,4 +605,4 @@ use PostScripton\Money\Money;
541605

542606
$money = new Money(1234);
543607
$money->toString(); // "$ 123.4"
544-
```
608+
```

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "postscripton/laravel-money",
33
"description": "A convenient way to convert numbers from DB or inputs into money strings for humans",
4-
"version": "2.1.0",
4+
"version": "2.2.0",
55
"type": "library",
66
"license": "MIT",
77
"authors": [

config/money.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,23 @@
1616
*/
1717
'default_currency' => 'USD',
1818

19+
/*
20+
|--------------------------------------------------------------------------
21+
| Currency Lists
22+
|--------------------------------------------------------------------------
23+
|
24+
| This option controls which list of currencies will be used.
25+
|
26+
| For now following lists are provided:
27+
| 1. all - all the currencies in the world.
28+
| 2. popular - only the most popular ones (35) are used. (default)
29+
|
30+
| Segregation of currencies is assumed for performance purposes so that
31+
| unnecessary ones won't be used.
32+
|
33+
*/
34+
'currency_list' => 'popular',
35+
1936
/*
2037
|--------------------------------------------------------------------------
2138
| Thousands separator

src/Currency.php

Lines changed: 109 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
namespace PostScripton\Money;
44

5+
use Illuminate\Support\Collection;
56
use PostScripton\Money\Exceptions\CurrencyDoesNotExistException;
7+
use PostScripton\Money\Exceptions\CurrencyHasWrongConstructorException;
8+
use PostScripton\Money\Exceptions\CurrencyListConfigException;
9+
use PostScripton\Money\Exceptions\NoSuchCurrencySymbolException;
610
use PostScripton\Money\Exceptions\ShouldPublishConfigFileException;
711

812
class Currency
@@ -12,38 +16,76 @@ class Currency
1216
public const POS_START = 0;
1317
public const POS_END = 1;
1418

19+
public const DISPLAY_SYMBOL = 10;
20+
public const DISPLAY_CODE = 11;
21+
22+
public const LIST_ALL = 'all';
23+
public const LIST_POPULAR = 'popular';
24+
private static string $_list;
25+
1526
public static function code(string $code): ?Currency
1627
{
17-
$code = strtoupper($code);
28+
$currency = is_numeric($code)
29+
? self::currencies()->firstWhere('num_code', $code)
30+
: self::currencies()->firstWhere('iso_code', strtoupper($code));
1831

19-
if (!array_key_exists($code, self::all())) {
20-
throw new CurrencyDoesNotExistException(__METHOD__, 1, '$code', $code);
32+
if (is_null($currency)) {
33+
throw new CurrencyDoesNotExistException(__METHOD__, 1, '$code', implode(',', [$code, self::$_list]));
2134
}
2235

23-
$currency = self::all()[$code];
36+
return new Currency($currency);
37+
}
2438

25-
return new Currency($code, $currency['symbol'], $currency['position']);
39+
protected static function currencies(): Collection
40+
{
41+
if (!in_array(config('money.currency_list'), [self::LIST_ALL, self::LIST_POPULAR])) {
42+
throw new CurrencyListConfigException(config('money.currency_list'));
43+
}
44+
45+
if (!self::$currencies) {
46+
self::setCurrencyList(config('money.currency_list'));
47+
}
48+
49+
return collect(self::$currencies);
2650
}
2751

28-
protected static function all(): array
52+
public static function setCurrencyList(string $list = self::LIST_POPULAR)
2953
{
30-
if (!static::$currencies) {
31-
static::$currencies = require __DIR__ . '/List/currencies.php';
54+
if ($list !== self::LIST_ALL && $list !== self::LIST_POPULAR) {
55+
$list = self::LIST_POPULAR;
3256
}
33-
return static::$currencies;
57+
58+
self::$currencies = require __DIR__ . "/List/{$list}_currencies.php";
59+
self::$_list = $list;
3460
}
3561

3662
// ==================== OBJECT ==================== //
3763

38-
private string $code;
39-
private string $symbol;
40-
private string $position;
64+
private string $full_name;
65+
private string $name;
66+
private string $iso_code;
67+
private string $num_code;
68+
private $symbol; // array or string
69+
private int $position;
70+
private int $display;
4171

42-
public function __construct(string $code, string $symbol, ?int $position = null)
72+
public function __construct(array $currency)
4373
{
44-
$this->code = $code;
45-
$this->symbol = $symbol;
46-
$this->position = $position ?? self::POS_START;
74+
if (is_null($currency['full_name']) ||
75+
is_null($currency['name']) ||
76+
is_null($currency['iso_code']) ||
77+
is_null($currency['num_code']) ||
78+
is_null($currency['symbol'])) {
79+
throw new CurrencyHasWrongConstructorException();
80+
}
81+
82+
$this->full_name = $currency['full_name'];
83+
$this->name = $currency['name'];
84+
$this->iso_code = $currency['iso_code'];
85+
$this->num_code = $currency['num_code'];
86+
$this->symbol = $currency['symbol'];
87+
$this->position = $currency['position'] ?? self::POS_END;
88+
$this->display = self::DISPLAY_SYMBOL;
4789
}
4890

4991
/**
@@ -58,13 +100,45 @@ public static function getConfigCurrency(): string
58100
return config('money.default_currency', 'USD');
59101
}
60102

103+
public function getFullName(): string
104+
{
105+
return $this->full_name;
106+
}
107+
108+
public function getName(): string
109+
{
110+
return $this->name;
111+
}
112+
61113
public function getCode(): string
62114
{
63-
return $this->code;
115+
return $this->iso_code;
64116
}
65117

66-
public function getSymbol(): string
118+
public function getNumCode(): string
67119
{
120+
return $this->num_code;
121+
}
122+
123+
public function getSymbol(int $index = 0): string
124+
{
125+
if ($this->display === self::DISPLAY_CODE) {
126+
return $this->iso_code;
127+
}
128+
129+
if (is_array($this->symbol)) {
130+
if (!array_key_exists($index, $this->symbol)) {
131+
throw new NoSuchCurrencySymbolException(
132+
__METHOD__,
133+
1,
134+
'$index',
135+
implode(',', [$index, count($this->symbol) - 1])
136+
);
137+
}
138+
139+
return $this->symbol[$index];
140+
}
141+
68142
return $this->symbol;
69143
}
70144

@@ -73,13 +147,28 @@ public function getPosition(): int
73147
return $this->position;
74148
}
75149

76-
public function setPosition(string $position): Currency
150+
public function getDisplay(): int
151+
{
152+
return $this->display;
153+
}
154+
155+
public function setPosition(int $position = self::POS_START): self
77156
{
78-
if ($position !== self::POS_START || $position !== self::POS_END) {
157+
if ($position !== self::POS_START && $position !== self::POS_END) {
79158
$position = self::POS_START;
80159
}
81160

82161
$this->position = $position;
83162
return $this;
84163
}
164+
165+
public function setDisplay(int $display = self::DISPLAY_SYMBOL): self
166+
{
167+
if ($display !== self::DISPLAY_SYMBOL && $display !== self::DISPLAY_CODE) {
168+
$display = self::DISPLAY_SYMBOL;
169+
}
170+
171+
$this->display = $display;
172+
return $this;
173+
}
85174
}

src/Exceptions/CurrencyDoesNotExistException.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ public function __construct(
1212
$code = 0,
1313
BaseException $previous = null
1414
) {
15+
$message = explode(',', $message);
1516
parent::__construct(
1617
$method,
1718
$arg_num,
1819
$arg_name,
1920
'must have standard currency code: alphabetical or numeric',
20-
"The currency \"{$message}\" doesn't exist",
21+
"The currency \"{$message[0]}\" doesn't exist in the list \"{$message[1]}\"",
2122
$code,
2223
$previous
2324
);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace PostScripton\Money\Exceptions;
4+
5+
use PostScripton\Money\Currency;
6+
7+
class CurrencyHasWrongConstructorException extends BaseException
8+
{
9+
public function __construct($code = 0, BaseException $previous = null)
10+
{
11+
parent::__construct(
12+
Currency::class . ' got wrong array as a parameter for constructor thus it can not be instantiated.',
13+
$code,
14+
$previous
15+
);
16+
}
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace PostScripton\Money\Exceptions;
4+
5+
class CurrencyListConfigException extends BaseException
6+
{
7+
public function __construct(string $value, $code = 0, BaseException $previous = null)
8+
{
9+
parent::__construct(
10+
"'The config value \"money.currency_list\" must be \"all\" or \"popular\". The value \"{$value}\" was given.'",
11+
$code,
12+
$previous
13+
);
14+
}
15+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace PostScripton\Money\Exceptions;
4+
5+
class NoSuchCurrencySymbolException extends ValueErrorException
6+
{
7+
public function __construct(
8+
string $method,
9+
int $arg_num,
10+
string $arg_name = null,
11+
string $message = null,
12+
$code = 0,
13+
BaseException $previous = null
14+
) {
15+
$message = explode(',', $message);
16+
parent::__construct(
17+
$method,
18+
$arg_num,
19+
$arg_name,
20+
"[{$message[0]}] is out of bounds. The range [0-{$message[1]}] is supposed",
21+
null,
22+
$code,
23+
$previous
24+
);
25+
}
26+
}

0 commit comments

Comments
 (0)