diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..38cdbd7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/vendor
+composer.phar
+composer.lock
+.DS_Store
+.idea
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..bd90834
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,15 @@
+language: php
+
+php:
+ - 7.2
+ - 7.3
+ - 7.4
+ - 8.0
+
+before_script:
+ - curl -s http://getcomposer.org/installer | php
+ - php composer.phar install --dev
+
+script:
+ - ./vendor/bin/phpcs --standard=phpcs.xml src
+ - ./vendor/bin/phpstan --level=0 --no-progress analyse src
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..76476ce
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,11 @@
+The BSD 2-Clause License
+Copyright (c) 2016-2020, Daniel Stainback
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a2dcc1b
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# currency
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..69e2605
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,57 @@
+{
+ "name": "forexapi/currency",
+ "description": "This provides Laravel with currency functions such as currency formatting and conversion using up-to-date exchange rates.",
+ "keywords": [
+ "laravel",
+ "currency",
+ "money",
+ "exchange rate",
+ "OpenExchangeRates",
+ "Exchange Rates API",
+ "finance"
+ ],
+ "license": "BSD-2-Clause",
+ "authors": [
+ {
+ "name": "Daniel Stainback",
+ "email": "ForexAPI@gmail.com"
+ },
+ {
+ "name": "CHapdel KAMGA",
+ "email": "drop@chapdel.me"
+ }
+ ],
+ "require": {
+ "php": "^7.2|^8.0",
+ "illuminate/support": "^6.0|^7.0|^8.0",
+ "illuminate/console": "^6.0|^7.0|^8.0",
+ "illuminate/cache": "^6.0|^7.0|^8.0"
+ },
+ "suggest": {
+ "illuminate/database": "Allows for storing of currencies in the database"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.0",
+ "mockery/mockery": "^1.3",
+ "phpstan/phpstan": "^0.12.14",
+ "squizlabs/php_codesniffer": "^3.5"
+ },
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "ForexAPI\\Currency\\": "src/"
+ }
+ },
+ "extra": {
+ "laravel": {
+ "providers": [
+ "ForexAPI\\Currency\\CurrencyServiceProvider"
+ ],
+ "aliases": {
+ "Currency": "ForexAPI\\Currency\\Facades\\Currency"
+ }
+ }
+ }
+}
diff --git a/config/currency.php b/config/currency.php
new file mode 100644
index 0000000..3b09908
--- /dev/null
+++ b/config/currency.php
@@ -0,0 +1,121 @@
+ 'USD',
+
+ /*
+ |--------------------------------------------------------------------------
+ | API Key for FOREXAPI
+ |--------------------------------------------------------------------------
+ |
+ | Only required if you with to use the Open Exchange Rates api. You can
+ | always just use Yahoo, the current default.
+ |
+ */
+
+ 'api_key' => env(
+ "FOREXAPI_KEY",
+ ),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Default Storage Driver
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the default storage driver that should be used
+ | by the framework.
+ |
+ | Supported: "database", "filesystem", "Model"
+ |
+ */
+
+ 'driver' => 'model',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Default Storage 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' => null,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Storage Specific Configuration
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure as many storage drivers as you wish.
+ |
+ */
+
+ 'drivers' => [
+
+ 'database' => [
+ 'class' => \ForexAPI\Currency\Drivers\Database::class,
+ 'connection' => null,
+ 'table' => 'currencies',
+ ],
+
+ 'filesystem' => [
+ 'class' => \ForexAPI\Currency\Drivers\Filesystem::class,
+ 'disk' => null,
+ 'path' => 'currencies.json',
+ ],
+
+ 'model' => [
+ 'table' => 'currencies',
+ 'class' => Currency::class
+ ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Currency Formatter
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure a custom formatting of currencies. The reason for
+ | this is to help further internationalize the formatting past the basic
+ | format column in the table. When set to `null` the package will use the
+ | format from storage.
+ |
+ |
+ */
+
+ 'formatter' => null,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Currency Formatter Specific Configuration
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure as many currency formatters as you wish.
+ |
+ */
+
+ 'formatters' => [
+
+ 'php_intl' => [
+ 'class' => \ForexAPI\Currency\Formatters\PHPIntl::class,
+ ],
+
+ ],
+];
diff --git a/database/migrations/2013_11_26_161501_create_currency_table.php b/database/migrations/2013_11_26_161501_create_currency_table.php
new file mode 100644
index 0000000..7161565
--- /dev/null
+++ b/database/migrations/2013_11_26_161501_create_currency_table.php
@@ -0,0 +1,50 @@
+table_name = config('currency.drivers.database.table');
+ }
+
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create($this->table_name, function ($table) {
+ $table->increments('id')->unsigned();
+ $table->string('name');
+ $table->string('code', 10)->index();
+ $table->string('symbol', 25);
+ $table->string('format', 50);
+ $table->string('exchange_rate');
+ $table->boolean('active')->default(false);
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop($this->table_name);
+ }
+}
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 0000000..6ca6aac
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,26 @@
+
+
+ The PSR2 standard
+
+
+ /resources/
+ /vendor/
+ /_[a-zA-Z0-9\._]+\.php
+ /\.[a-zA-Z0-9\._]+\.php
+ \.git
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..567a070
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,10 @@
+parameters:
+ excludes_analyse:
+ - vendor
+ - resources
+ ignoreErrors:
+ - '#Function app not found#'
+ - '#Function config_path not found#'
+ - '#Function base_path not found#'
+ - '#Function config not found#'
+ - '#Parameter \$request of method#'
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..12bee7a
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ ./tests/
+
+
+
\ No newline at end of file
diff --git a/resources/currencies.php b/resources/currencies.php
new file mode 100644
index 0000000..bf6151d
--- /dev/null
+++ b/resources/currencies.php
@@ -0,0 +1,953 @@
+ [
+ 'name' => 'UAE Dirham',
+ 'symbol' => 'دإ',
+ 'format' => 'دإ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'AFN' => [
+ 'name' => 'Afghanistan, Afghani',
+ 'symbol' => '؋',
+ 'format' => '؋1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'ALL' => [
+ 'name' => 'Albania, Lek',
+ 'symbol' => 'Lek',
+ 'format' => '1,0.00Lek',
+ 'exchange_rate' => 0.00,
+ ],
+ 'AMD' => [
+ 'name' => 'Armenian Dram',
+ 'symbol' => '֏',
+ 'format' => '1,0.00 ֏',
+ 'exchange_rate' => 0.00,
+ ],
+ 'ANG' => [
+ 'name' => 'Netherlands Antillian Guilder',
+ 'symbol' => 'ƒ',
+ 'format' => 'ƒ1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'AOA' => [
+ 'name' => 'Angola, Kwanza',
+ 'symbol' => 'Kz',
+ 'format' => 'Kz1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'ARS' => [
+ 'name' => 'Argentine Peso',
+ 'symbol' => '$',
+ 'format' => '$ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'AUD' => [
+ 'name' => 'Australian Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'AWG' => [
+ 'name' => 'Aruban Guilder',
+ 'symbol' => 'ƒ',
+ 'format' => 'ƒ1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'AZN' => [
+ 'name' => 'Azerbaijanian Manat',
+ 'symbol' => '₼',
+ 'format' => '1 0,00 ₼',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BAM' => [
+ 'name' => 'Bosnia and Herzegovina, Convertible Marks',
+ 'symbol' => 'КМ',
+ 'format' => '1,0.00 КМ',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BBD' => [
+ 'name' => 'Barbados Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BDT' => [
+ 'name' => 'Bangladesh, Taka',
+ 'symbol' => '৳',
+ 'format' => '৳ 1,0.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BGN' => [
+ 'name' => 'Bulgarian Lev',
+ 'symbol' => 'лв.',
+ 'format' => '1 0,00 лв.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BHD' => [
+ 'name' => 'Bahraini Dinar',
+ 'symbol' => '.د.',
+ 'format' => '.د. 1,0.000',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BIF' => [
+ 'name' => 'Burundi Franc',
+ 'symbol' => 'FBu',
+ 'format' => '1,0.FBu',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BMD' => [
+ 'name' => 'Bermudian Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BND' => [
+ 'name' => 'Brunei Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BOB' => [
+ 'name' => 'Bolivia, Boliviano',
+ 'symbol' => 'Bs',
+ 'format' => 'Bs 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BRL' => [
+ 'name' => 'Brazilian Real',
+ 'symbol' => 'R$',
+ 'format' => 'R$ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BSD' => [
+ 'name' => 'Bahamian Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BTN' => [
+ 'name' => 'Bhutan, Ngultrum',
+ 'symbol' => 'Nu.',
+ 'format' => 'Nu. 1,0.0',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BWP' => [
+ 'name' => 'Botswana, Pula',
+ 'symbol' => 'P',
+ 'format' => 'P1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BYN' => [
+ 'name' => 'Belarussian Ruble',
+ 'symbol' => 'р.',
+ 'format' => '1 0,00 р.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'BZD' => [
+ 'name' => 'Belize Dollar',
+ 'symbol' => 'BZ$',
+ 'format' => 'BZ$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'CAD' => [
+ 'name' => 'Canadian Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'CDF' => [
+ 'name' => 'Franc Congolais',
+ 'symbol' => 'FC',
+ 'format' => '1,0.00FC',
+ 'exchange_rate' => 0.00,
+ ],
+ 'CHF' => [
+ 'name' => 'Swiss Franc',
+ 'symbol' => 'CHF',
+ 'format' => '1\'0.00 CHF',
+ 'exchange_rate' => 0.00,
+ ],
+ 'CLP' => [
+ 'name' => 'Chilean Peso',
+ 'symbol' => '$',
+ 'format' => '$ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'CNY' => [
+ 'name' => 'China Yuan Renminbi',
+ 'symbol' => '¥',
+ 'format' => '¥1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'COP' => [
+ 'name' => 'Colombian Peso',
+ 'symbol' => '$',
+ 'format' => '$ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'CRC' => [
+ 'name' => 'Costa Rican Colon',
+ 'symbol' => '₡',
+ 'format' => '₡1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'CUC' => [
+ 'name' => 'Cuban Convertible Peso',
+ 'symbol' => 'CUC',
+ 'format' => 'CUC1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'CUP' => [
+ 'name' => 'Cuban Peso',
+ 'symbol' => '$MN',
+ 'format' => '$MN1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'CVE' => [
+ 'name' => 'Cape Verde Escudo',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'CZK' => [
+ 'name' => 'Czech Koruna',
+ 'symbol' => 'Kč',
+ 'format' => '1 0,00 Kč',
+ 'exchange_rate' => 0.00,
+ ],
+ 'DJF' => [
+ 'name' => 'Djibouti Franc',
+ 'symbol' => 'Fdj',
+ 'format' => '1,0.Fdj',
+ 'exchange_rate' => 0.00,
+ ],
+ 'DKK' => [
+ 'name' => 'Danish Krone',
+ 'symbol' => 'kr.',
+ 'format' => '1 0,00 kr.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'DOP' => [
+ 'name' => 'Dominican Peso',
+ 'symbol' => 'RD$',
+ 'format' => 'RD$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'DZD' => [
+ 'name' => 'Algerian Dinar',
+ 'symbol' => 'د.ج',
+ 'format' => 'د.ج 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'EGP' => [
+ 'name' => 'Egyptian Pound',
+ 'symbol' => 'ج.م',
+ 'format' => 'ج.م 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'ERN' => [
+ 'name' => 'Eritrea, Nakfa',
+ 'symbol' => 'Nfk',
+ 'format' => '1,0.00Nfk',
+ 'exchange_rate' => 0.00,
+ ],
+ 'ETB' => [
+ 'name' => 'Ethiopian Birr',
+ 'symbol' => 'ETB',
+ 'format' => 'ETB1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'EUR' => [
+ 'name' => 'Euro',
+ 'symbol' => '€',
+ 'format' => '1.0,00 €',
+ 'exchange_rate' => 0.00,
+ ],
+ 'FJD' => [
+ 'name' => 'Fiji Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'FKP' => [
+ 'name' => 'Falkland Islands Pound',
+ 'symbol' => '£',
+ 'format' => '£1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'GBP' => [
+ 'name' => 'Pound Sterling',
+ 'symbol' => '£',
+ 'format' => '£1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'GEL' => [
+ 'name' => 'Georgia, Lari',
+ 'symbol' => 'Lari',
+ 'format' => '1 0,00 Lari',
+ 'exchange_rate' => 0.00,
+ ],
+ 'GHS' => [
+ 'name' => 'Ghana Cedi',
+ 'symbol' => '₵',
+ 'format' => '₵1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'GIP' => [
+ 'name' => 'Gibraltar Pound',
+ 'symbol' => '£',
+ 'format' => '£1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'GMD' => [
+ 'name' => 'Gambia, Dalasi',
+ 'symbol' => 'D',
+ 'format' => '1,0.00D',
+ 'exchange_rate' => 0.00,
+ ],
+ 'GNF' => [
+ 'name' => 'Guinean franc',
+ 'symbol' => 'FG',
+ 'format' => '1,0.00FG',
+ 'exchange_rate' => 0.00,
+ ],
+ 'GTQ' => [
+ 'name' => 'Guatemala, Quetzal',
+ 'symbol' => 'Q',
+ 'format' => 'Q1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'GYD' => [
+ 'name' => 'Guyana Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'HKD' => [
+ 'name' => 'Hong Kong Dollar',
+ 'symbol' => 'HK$',
+ 'format' => 'HK$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'HNL' => [
+ 'name' => 'Honduras, Lempira',
+ 'symbol' => 'L.',
+ 'format' => 'L. 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'HRK' => [
+ 'name' => 'Croatian Kuna',
+ 'symbol' => 'kn',
+ 'format' => '1,0.00 kn',
+ 'exchange_rate' => 0.00,
+ ],
+ 'HTG' => [
+ 'name' => 'Haiti, Gourde',
+ 'symbol' => 'G',
+ 'format' => 'G1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'HUF' => [
+ 'name' => 'Hungary, Forint',
+ 'symbol' => 'Ft',
+ 'format' => '1 0,00 Ft',
+ 'exchange_rate' => 0.00,
+ ],
+ 'IDR' => [
+ 'name' => 'Indonesia, Rupiah',
+ 'symbol' => 'Rp',
+ 'format' => 'Rp1,0.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'ILS' => [
+ 'name' => 'New Israeli Shekel',
+ 'symbol' => '₪',
+ 'format' => '₪ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'INR' => [
+ 'name' => 'Indian Rupee',
+ 'symbol' => '₹',
+ 'format' => '1,0.00₹',
+ 'exchange_rate' => 0.00,
+ ],
+ 'IQD' => [
+ 'name' => 'Iraqi Dinar',
+ 'symbol' => 'د.ع.',
+ 'format' => 'د.ع. 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'IRR' => [
+ 'name' => 'Iranian Rial',
+ 'symbol' => '﷼',
+ 'format' => '﷼ 1,0/00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'ISK' => [
+ 'name' => 'Iceland Krona',
+ 'symbol' => 'kr.',
+ 'format' => '1,0. kr.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'JMD' => [
+ 'name' => 'Jamaican Dollar',
+ 'symbol' => 'J$',
+ 'format' => 'J$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'JOD' => [
+ 'name' => 'Jordanian Dinar',
+ 'symbol' => 'د.ا.',
+ 'format' => 'د.ا. 1,0.000',
+ 'exchange_rate' => 0.00,
+ ],
+ 'JPY' => [
+ 'name' => 'Japan, Yen',
+ 'symbol' => '¥',
+ 'format' => '¥1,0.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'KES' => [
+ 'name' => 'Kenyan Shilling',
+ 'symbol' => 'S',
+ 'format' => 'S1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'KGS' => [
+ 'name' => 'Kyrgyzstan, Som',
+ 'symbol' => 'сом',
+ 'format' => '1 0-00 сом',
+ 'exchange_rate' => 0.00,
+ ],
+ 'KHR' => [
+ 'name' => 'Cambodia, Riel',
+ 'symbol' => '៛',
+ 'format' => '1,0.៛',
+ 'exchange_rate' => 0.00,
+ ],
+ 'KMF' => [
+ 'name' => 'Comoro Franc',
+ 'symbol' => 'CF',
+ 'format' => '1,0.00CF',
+ 'exchange_rate' => 0.00,
+ ],
+ 'KPW' => [
+ 'name' => 'North Korean Won',
+ 'symbol' => '₩',
+ 'format' => '₩1,0.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'KRW' => [
+ 'name' => 'South Korea, Won',
+ 'symbol' => '₩',
+ 'format' => '₩1,0.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'KWD' => [
+ 'name' => 'Kuwaiti Dinar',
+ 'symbol' => 'دينار',
+ 'format' => 'دينار 1,0.000',
+ 'exchange_rate' => 0.00,
+ ],
+ 'KYD' => [
+ 'name' => 'Cayman Islands Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'KZT' => [
+ 'name' => 'Kazakhstan, Tenge',
+ 'symbol' => '₸',
+ 'format' => '₸1 0-00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'LAK' => [
+ 'name' => 'Laos, Kip',
+ 'symbol' => '₭',
+ 'format' => '1,0.₭',
+ 'exchange_rate' => 0.00,
+ ],
+ 'LBP' => [
+ 'name' => 'Lebanese Pound',
+ 'symbol' => 'ل.ل.',
+ 'format' => 'ل.ل. 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'LKR' => [
+ 'name' => 'Sri Lanka Rupee',
+ 'symbol' => '₨',
+ 'format' => '₨ 1,0.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'LRD' => [
+ 'name' => 'Liberian Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'LSL' => [
+ 'name' => 'Lesotho, Loti',
+ 'symbol' => 'M',
+ 'format' => '1,0.00M',
+ 'exchange_rate' => 0.00,
+ ],
+ 'LYD' => [
+ 'name' => 'Libyan Dinar',
+ 'symbol' => 'د.ل.',
+ 'format' => 'د.ل.1,0.000',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MAD' => [
+ 'name' => 'Moroccan Dirham',
+ 'symbol' => 'د.م.',
+ 'format' => 'د.م. 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MDL' => [
+ 'name' => 'Moldovan Leu',
+ 'symbol' => 'lei',
+ 'format' => '1,0.00 lei',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MGA' => [
+ 'name' => 'Malagasy Ariary',
+ 'symbol' => 'Ar',
+ 'format' => 'Ar1,0.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MKD' => [
+ 'name' => 'Macedonia, Denar',
+ 'symbol' => 'ден.',
+ 'format' => '1,0.00 ден.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MMK' => [
+ 'name' => 'Myanmar, Kyat',
+ 'symbol' => 'K',
+ 'format' => 'K1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MNT' => [
+ 'name' => 'Mongolia, Tugrik',
+ 'symbol' => '₮',
+ 'format' => '₮1 0,00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MOP' => [
+ 'name' => 'Macao, Pataca',
+ 'symbol' => 'MOP$',
+ 'format' => 'MOP$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MRU' => [
+ 'name' => 'Mauritania, Ouguiya',
+ 'symbol' => 'UM',
+ 'format' => '1,0.00UM',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MTL' => [
+ 'name' => 'Maltese Lira',
+ 'symbol' => '₤',
+ 'format' => '₤1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MUR' => [
+ 'name' => 'Mauritius Rupee',
+ 'symbol' => '₨',
+ 'format' => '₨1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MVR' => [
+ 'name' => 'Maldives, Rufiyaa',
+ 'symbol' => 'MVR',
+ 'format' => '1,0.0 MVR',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MWK' => [
+ 'name' => 'Malawi, Kwacha',
+ 'symbol' => 'MK',
+ 'format' => 'MK1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MXN' => [
+ 'name' => 'Mexican Peso',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MYR' => [
+ 'name' => 'Malaysian Ringgit',
+ 'symbol' => 'RM',
+ 'format' => 'RM1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'MZN' => [
+ 'name' => 'Mozambique Metical',
+ 'symbol' => 'MT',
+ 'format' => 'MT1,0.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'NAD' => [
+ 'name' => 'Namibian Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'NGN' => [
+ 'name' => 'Nigeria, Naira',
+ 'symbol' => '₦',
+ 'format' => '₦1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'NIO' => [
+ 'name' => 'Nicaragua, Cordoba Oro',
+ 'symbol' => 'C$',
+ 'format' => 'C$ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'NOK' => [
+ 'name' => 'Norwegian Krone',
+ 'symbol' => 'kr',
+ 'format' => '1.0,00 kr',
+ 'exchange_rate' => 0.00,
+ ],
+ 'NPR' => [
+ 'name' => 'Nepalese Rupee',
+ 'symbol' => '₨',
+ 'format' => '₨1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'NZD' => [
+ 'name' => 'New Zealand Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'OMR' => [
+ 'name' => 'Rial Omani',
+ 'symbol' => '﷼',
+ 'format' => '﷼ 1,0.000',
+ 'exchange_rate' => 0.00,
+ ],
+ 'PAB' => [
+ 'name' => 'Panama, Balboa',
+ 'symbol' => 'B/.',
+ 'format' => 'B/. 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'PEN' => [
+ 'name' => 'Peru, Nuevo Sol',
+ 'symbol' => 'S/.',
+ 'format' => 'S/. 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'PGK' => [
+ 'name' => 'Papua New Guinea, Kina',
+ 'symbol' => 'K',
+ 'format' => 'K1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'PHP' => [
+ 'name' => 'Philippine Peso',
+ 'symbol' => '₱',
+ 'format' => '₱1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'PKR' => [
+ 'name' => 'Pakistan Rupee',
+ 'symbol' => '₨',
+ 'format' => '₨1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'PLN' => [
+ 'name' => 'Poland, Zloty',
+ 'symbol' => 'zł',
+ 'format' => '1 0,00 zł',
+ 'exchange_rate' => 0.00,
+ ],
+ 'PYG' => [
+ 'name' => 'Paraguay, Guarani',
+ 'symbol' => '₲',
+ 'format' => '₲ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'QAR' => [
+ 'name' => 'Qatari Rial',
+ 'symbol' => '﷼',
+ 'format' => '﷼ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'RON' => [
+ 'name' => 'Romania, New Leu',
+ 'symbol' => 'lei',
+ 'format' => '1,0.00 lei',
+ 'exchange_rate' => 0.00,
+ ],
+ 'RSD' => [
+ 'name' => 'Serbian Dinar',
+ 'symbol' => 'Дин.',
+ 'format' => '1,0.00 Дин.',
+ 'exchange_rate' => 0.00,
+ ],
+ 'RUB' => [
+ 'name' => 'Russian Ruble',
+ 'symbol' => '₽',
+ 'format' => '1 0,00 ₽',
+ 'exchange_rate' => 0.00,
+ ],
+ 'RWF' => [
+ 'name' => 'Rwanda Franc',
+ 'symbol' => 'RWF',
+ 'format' => 'RWF 1 0,00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SAR' => [
+ 'name' => 'Saudi Riyal',
+ 'symbol' => '﷼',
+ 'format' => '﷼ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SBD' => [
+ 'name' => 'Solomon Islands Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SCR' => [
+ 'name' => 'Seychelles Rupee',
+ 'symbol' => '₨',
+ 'format' => '₨1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SDG' => [
+ 'name' => 'Sudanese Pound',
+ 'symbol' => 'ج.س',
+ 'format' => '1,0.00 Sd',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SEK' => [
+ 'name' => 'Swedish Krona',
+ 'symbol' => 'kr',
+ 'format' => '1 0,00 kr',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SGD' => [
+ 'name' => 'Singapore Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SHP' => [
+ 'name' => 'Saint Helena Pound',
+ 'symbol' => '£',
+ 'format' => '£1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SLL' => [
+ 'name' => 'Sierra Leone, Leone',
+ 'symbol' => 'Le',
+ 'format' => 'Le1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SOS' => [
+ 'name' => 'Somali Shilling',
+ 'symbol' => 'S',
+ 'format' => 'S1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SRD' => [
+ 'name' => 'Surinam Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SSP' => [
+ 'name' => 'South Sudanese pound',
+ 'symbol' => 'SS£',
+ 'format' => 'SS £1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'STN' => [
+ 'name' => 'Sao Tome and Principe, Dobra',
+ 'symbol' => 'Db',
+ 'format' => 'Db1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SVC' => [
+ 'name' => 'El Salvador Colon',
+ 'symbol' => '₡',
+ 'format' => '₡1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SYP' => [
+ 'name' => 'Syrian Pound',
+ 'symbol' => '£',
+ 'format' => '£ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'SZL' => [
+ 'name' => 'Swaziland, Lilangeni',
+ 'symbol' => 'E',
+ 'format' => 'E1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'THB' => [
+ 'name' => 'Thailand, Baht',
+ 'symbol' => '฿',
+ 'format' => '฿1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'TJS' => [
+ 'name' => 'Tajikistan, Somoni',
+ 'symbol' => 'TJS',
+ 'format' => '1 0;00 TJS',
+ 'exchange_rate' => 0.00,
+ ],
+ 'TMT' => [
+ 'name' => 'Turkmenistani New Manat',
+ 'symbol' => 'm',
+ 'format' => '1 0,m',
+ 'exchange_rate' => 0.00,
+ ],
+ 'TND' => [
+ 'name' => 'Tunisian Dinar',
+ 'symbol' => 'د.ت.',
+ 'format' => 'د.ت. 1,0.000',
+ 'exchange_rate' => 0.00,
+ ],
+ 'TOP' => [
+ 'name' => 'Tonga, Paanga',
+ 'symbol' => 'T$',
+ 'format' => 'T$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'TRY' => [
+ 'name' => 'Turkish Lira',
+ 'symbol' => 'TL',
+ 'format' => '₺1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'TTD' => [
+ 'name' => 'Trinidad and Tobago Dollar',
+ 'symbol' => 'TT$',
+ 'format' => 'TT$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'TWD' => [
+ 'name' => 'New Taiwan Dollar',
+ 'symbol' => 'NT$',
+ 'format' => 'NT$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'TZS' => [
+ 'name' => 'Tanzanian Shilling',
+ 'symbol' => 'TSh',
+ 'format' => 'TSh1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'UAH' => [
+ 'name' => 'Ukraine, Hryvnia',
+ 'symbol' => '₴',
+ 'format' => '1 0,00₴',
+ 'exchange_rate' => 0.00,
+ ],
+ 'UGX' => [
+ 'name' => 'Uganda Shilling',
+ 'symbol' => 'USh',
+ 'format' => 'USh1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'USD' => [
+ 'name' => 'US Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'UYU' => [
+ 'name' => 'Peso Uruguayo',
+ 'symbol' => '$U',
+ 'format' => '$U 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'UZS' => [
+ 'name' => 'Uzbekistan Sum',
+ 'symbol' => 'сўм',
+ 'format' => '1 0,00 сўм',
+ 'exchange_rate' => 0.00,
+ ],
+ 'VES' => [
+ 'name' => 'Venezuela Bolivares soberano',
+ 'symbol' => 'Bs. S.',
+ 'format' => 'Bs. S. 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'VND' => [
+ 'name' => 'Viet Nam, Dong',
+ 'symbol' => '₫',
+ 'format' => '1,0.0 ₫',
+ 'exchange_rate' => 0.00,
+ ],
+ 'VUV' => [
+ 'name' => 'Vanuatu, Vatu',
+ 'symbol' => 'VT',
+ 'format' => '1,0.VT',
+ 'exchange_rate' => 0.00,
+ ],
+ 'WST' => [
+ 'name' => 'Samoa, Tala',
+ 'symbol' => 'WS$',
+ 'format' => 'WS$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'XAF' => [
+ 'name' => 'Franc CFA (XAF)',
+ 'symbol' => 'F.CFA',
+ 'format' => '1,0.00 F.CFA',
+ 'exchange_rate' => 0.00,
+ ],
+ 'XCD' => [
+ 'name' => 'East Caribbean Dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'XOF' => [
+ 'name' => 'Franc CFA (XOF)',
+ 'symbol' => 'F.CFA',
+ 'format' => '1,0.00 F.CFA',
+ 'exchange_rate' => 0.00,
+ ],
+ 'XPF' => [
+ 'name' => 'CFP Franc',
+ 'symbol' => 'F',
+ 'format' => '1,0.00F',
+ 'exchange_rate' => 0.00,
+ ],
+ 'YER' => [
+ 'name' => 'Yemeni Rial',
+ 'symbol' => '﷼',
+ 'format' => '﷼ 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'ZAR' => [
+ 'name' => 'South Africa, Rand',
+ 'symbol' => 'R',
+ 'format' => 'R 1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'ZMW' => [
+ 'name' => 'Zambia Kwacha',
+ 'symbol' => 'ZK',
+ 'format' => 'ZK1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+ 'ZWL' => [
+ 'name' => 'Zimbabwean dollar',
+ 'symbol' => '$',
+ 'format' => '$1,0.00',
+ 'exchange_rate' => 0.00,
+ ],
+];
diff --git a/src/Console/Cleanup.php b/src/Console/Cleanup.php
new file mode 100644
index 0000000..08f7af2
--- /dev/null
+++ b/src/Console/Cleanup.php
@@ -0,0 +1,65 @@
+currency = app('currency');
+
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command for Laravel 5.4 and below
+ *
+ * @return void
+ */
+ public function fire()
+ {
+ $this->handle();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ // Clear cache
+ $this->currency->clearCache();
+ $this->comment('Currency cache cleaned.');
+
+ // Force the system to rebuild cache
+ $this->currency->getCurrencies();
+ $this->comment('Currency cache rebuilt.');
+ }
+}
diff --git a/src/Console/Hydrate.php b/src/Console/Hydrate.php
new file mode 100644
index 0000000..7e0e278
--- /dev/null
+++ b/src/Console/Hydrate.php
@@ -0,0 +1,126 @@
+storage = app('currency')->getDriver();
+
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command for Laravel 5.4 and below
+ *
+ * @return void
+ */
+ public function fire()
+ {
+ $this->handle();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+
+ //get rates form forexapi
+ $r = Http::withHeaders([
+ 'X-API-Key' => config('currency.api_key'),
+ ])->get('https://api.forexapi.world/rates');
+
+
+
+ if ($r->successful()) {
+
+ switch (config('currency.driver')) {
+ case 'model':
+ $model = config('currency.drivers.model.class');
+ $this->currencies = $model::all();
+
+ if (count($this->currencies) == 0) {
+ foreach ($r->json() as $rate) {
+ $model::create(Arr::only($rate, ['name', 'code', 'symbol', 'exchange_rate', 'fraction']));
+ }
+ } else {
+
+ foreach ($r->json() as $rate) {
+ $currency = $this->currencies->where("code", $rate['code'])->first();
+ $currency->update(Arr::only($rate, ['exchange_rate',]));
+ }
+ }
+
+ break;
+
+ case 'database':
+ $table = config('currency.drivers.database.table');
+ $this->currencies = DB::table($table)->get();
+
+ if (count($this->currencies) == 0) {
+ foreach ($r->json() as $rate) {
+ DB::table($table)->insert(Arr::only($rate, ['name', 'code', 'symbol', 'exchange_rate', 'fraction']));
+ }
+ } else {
+
+ foreach ($r->json() as $rate) {
+ $currency = $this->currencies->where("code", $rate['code'])->first();
+ $currency->update(Arr::only($rate, ['exchange_rate',]));
+ }
+ }
+
+ break;
+
+ default:
+ # code...
+ break;
+ }
+
+
+ $this->info("Rates hydrated from forexapi");
+ } else {
+
+ $this->error("Failed to fetch rates from forexapi");
+ }
+ }
+}
diff --git a/src/Contracts/DriverInterface.php b/src/Contracts/DriverInterface.php
new file mode 100644
index 0000000..15be4fa
--- /dev/null
+++ b/src/Contracts/DriverInterface.php
@@ -0,0 +1,52 @@
+config = $config;
+ $this->cache = $cache->store($this->config('cache_driver'));
+ }
+
+ /**
+ * Format given number.
+ *
+ * @param float $amount
+ * @param string $from
+ * @param string $to
+ * @param bool $format
+ *
+ * @return string|null
+ */
+ public function convert($amount, $from = null, $to = null, $format = true)
+ {
+ // Get currencies involved
+ $from = $from ?: $this->config('default');
+ $to = $to ?: $this->getUserCurrency();
+
+ // Get exchange rates
+ $from_rate = $this->getCurrencyProp($from, 'exchange_rate');
+ $to_rate = $this->getCurrencyProp($to, 'exchange_rate');
+
+ // Skip invalid to currency rates
+ if ($to_rate === null) {
+ return null;
+ }
+
+ try {
+ // Convert amount
+ if ($from === $to) {
+ $value = $amount;
+ } else {
+ $value = ($amount * $to_rate) / $from_rate;
+ }
+ } catch (\Exception $e) {
+ // Prevent invalid conversion or division by zero errors
+ return null;
+ }
+
+ // Should the result be formatted?
+ if ($format === true) {
+ return $this->format($value, $to);
+ }
+
+ // Return value
+ return $value;
+ }
+
+ /**
+ * Format the value into the desired currency.
+ *
+ * @param float $value
+ * @param string $code
+ * @param bool $include_symbol
+ *
+ * @return string
+ */
+ public function format($value, $code = null, $include_symbol = true)
+ {
+ // Get default currency if one is not set
+ $code = $code ?: $this->config('default');
+
+ // Remove unnecessary characters
+ $value = preg_replace('/[\s\',!]/', '', $value);
+
+ // Check for a custom formatter
+ if ($formatter = $this->getFormatter()) {
+ return $formatter->format($value, $code);
+ }
+
+ // Get the measurement format
+ $format = $this->getCurrencyProp($code, 'format');
+
+ // Value Regex
+ $valRegex = '/([0-9].*|)[0-9]/';
+
+ // Match decimal and thousand separators
+ preg_match_all('/[\s\',.!]/', $format, $separators);
+
+ if ($thousand = Arr::get($separators, '0.0', null)) {
+ if ($thousand == '!') {
+ $thousand = '';
+ }
+ }
+
+ $decimal = Arr::get($separators, '0.1', null);
+
+ // Match format for decimals count
+ preg_match($valRegex, $format, $valFormat);
+
+ $valFormat = Arr::get($valFormat, 0, 0);
+
+ // Count decimals length
+ $decimals = $decimal ? strlen(substr(strrchr($valFormat, $decimal), 1)) : 0;
+
+ // Do we have a negative value?
+ if ($negative = $value < 0 ? '-' : '') {
+ $value = $value * -1;
+ }
+
+ // Format the value
+ $value = number_format($value, $decimals, $decimal, $thousand);
+
+ switch ($this->config('driver')) {
+ case 'model':
+ $model = $this->config('drivers.model.class');
+ $currency = $model::where('code', $code)->first();
+ break;
+ case 'database':
+ $table = $this->config('drivers.model.table');
+ $currency = DB::table($table)->where('code', $code)->first();
+ break;
+ default:
+ # code...
+ break;
+ }
+
+ $value = number_format($value, $currency->fraction ?? 2, $decimal, $thousand);
+
+ // Apply the formatted measurement
+ if ($include_symbol) {
+ $value = preg_replace($valRegex, $value, $format);
+ }
+
+ // Return value
+ return $negative . $value;
+ }
+
+ /**
+ * Set user's currency.
+ *
+ * @param string $code
+ */
+ public function setUserCurrency($code)
+ {
+ $this->user_currency = strtoupper($code);
+ }
+
+ /**
+ * Return the user's currency code.
+ *
+ * @return string
+ */
+ public function getUserCurrency()
+ {
+ return $this->user_currency ?: $this->config('default');
+ }
+
+ /**
+ * Determine if the provided currency is valid.
+ *
+ * @param string $code
+ *
+ * @return array|null
+ */
+ public function hasCurrency($code)
+ {
+ return array_key_exists(strtoupper($code), $this->getCurrencies());
+ }
+
+ /**
+ * Determine if the provided currency is active.
+ *
+ * @param string $code
+ *
+ * @return bool
+ */
+ public function isActive($code)
+ {
+ return $code && (bool) Arr::get($this->getCurrency($code), 'active', false);
+ }
+
+ /**
+ * Return the current currency if the
+ * one supplied is not valid.
+ *
+ * @param string $code
+ *
+ * @return array|null
+ */
+ public function getCurrency($code = null)
+ {
+ $code = $code ?: $this->getUserCurrency();
+
+ return Arr::get($this->getCurrencies(), strtoupper($code));
+ }
+
+ /**
+ * Return all currencies.
+ *
+ * @return array
+ */
+ public function getCurrencies()
+ {
+ if ($this->currencies_cache === null) {
+ if (config('app.debug', false) === true) {
+ $this->currencies_cache = $this->getDriver()->all();
+ } else {
+ $this->currencies_cache = $this->cache->rememberForever('forexapi.currency', function () {
+ return $this->getDriver()->all();
+ });
+ }
+ }
+
+ return $this->currencies_cache;
+ }
+
+ /**
+ * Return all active currencies.
+ *
+ * @return array
+ */
+ public function getActiveCurrencies()
+ {
+ return array_filter($this->getCurrencies(), function ($currency) {
+ return $currency['active'] == true;
+ });
+ }
+
+ /**
+ * Get storage driver.
+ *
+ * @return \ForexAPI\Currency\Contracts\DriverInterface
+ */
+ public function getDriver()
+ {
+ if ($this->driver === null) {
+ // Get driver configuration
+ $config = $this->config('drivers.' . $this->config('driver'), []);
+
+ // Get driver class
+ $driver = Arr::pull($config, 'class');
+
+ // Create driver instance
+ $this->driver = new $driver($config);
+ }
+
+ return $this->driver;
+ }
+
+ /**
+ * Get formatter driver.
+ *
+ * @return \ForexAPI\Currency\Contracts\FormatterInterface
+ */
+ public function getFormatter()
+ {
+ if ($this->formatter === null && $this->config('formatter') !== null) {
+ // Get formatter configuration
+ $config = $this->config('formatters.' . $this->config('formatter'), []);
+
+ // Get formatter class
+ $class = Arr::pull($config, 'class');
+
+ // Create formatter instance
+ $this->formatter = new $class(array_filter($config));
+ }
+
+ return $this->formatter;
+ }
+
+ /**
+ * Clear cached currencies.
+ */
+ public function clearCache()
+ {
+ $this->cache->forget('forexapi.currency');
+ $this->currencies_cache = null;
+ }
+
+ /**
+ * Get configuration value.
+ *
+ * @param string $key
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function config($key = null, $default = null)
+ {
+ if ($key === null) {
+ return $this->config;
+ }
+
+ return Arr::get($this->config, $key, $default);
+ }
+
+ /**
+ * Get the given property value from provided currency.
+ *
+ * @param string $code
+ * @param string $key
+ * @param mixed $default
+ *
+ * @return array
+ */
+ protected function getCurrencyProp($code, $key, $default = null)
+ {
+ return Arr::get($this->getCurrency($code), $key, $default);
+ }
+
+ /**
+ * Get a given value from the current currency.
+ *
+ * @param string $key
+ *
+ * @return mixed
+ */
+ public function __get($key)
+ {
+ return Arr::get($this->getCurrency(), $key);
+ }
+
+ /**
+ * Dynamically call the default driver instance.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ return call_user_func_array([$this->getDriver(), $method], $parameters);
+ }
+}
diff --git a/src/CurrencyServiceProvider.php b/src/CurrencyServiceProvider.php
new file mode 100644
index 0000000..2143141
--- /dev/null
+++ b/src/CurrencyServiceProvider.php
@@ -0,0 +1,85 @@
+registerCurrency();
+
+ if ($this->app->runningInConsole()) {
+ $this->registerResources();
+ $this->registerCurrencyCommands();
+ }
+ }
+
+ /**
+ * Register currency provider.
+ *
+ * @return void
+ */
+ public function registerCurrency()
+ {
+ $this->app->singleton('currency', function ($app) {
+ return new Currency(
+ $app->config->get('currency', []),
+ $app['cache']
+ );
+ });
+ }
+
+ /**
+ * Register currency resources.
+ *
+ * @return void
+ */
+ public function registerResources()
+ {
+ if ($this->isLumen() === false) {
+ $this->publishes([
+ __DIR__ . '/../config/currency.php' => config_path('currency.php'),
+ ], 'config');
+
+ $this->mergeConfigFrom(
+ __DIR__ . '/../config/currency.php',
+ 'currency'
+ );
+ }
+
+ $this->publishes([
+ __DIR__ . '/../database/migrations' => base_path('/database/migrations'),
+ ], 'migrations');
+ }
+
+ /**
+ * Register currency commands.
+ *
+ * @return void
+ */
+ public function registerCurrencyCommands()
+ {
+ $this->commands([
+ Console\Cleanup::class,
+ Console\Hydrate::class,
+ ]);
+ }
+
+ /**
+ * Check if package is running under Lumen app
+ *
+ * @return bool
+ */
+ protected function isLumen()
+ {
+ return Str::contains($this->app->version(), 'Lumen') === true;
+ }
+}
diff --git a/src/Drivers/AbstractDriver.php b/src/Drivers/AbstractDriver.php
new file mode 100644
index 0000000..c2361d9
--- /dev/null
+++ b/src/Drivers/AbstractDriver.php
@@ -0,0 +1,39 @@
+config = $config;
+ }
+
+ /**
+ * Get configuration value.
+ *
+ * @param string $key
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ protected function config($key, $default = null)
+ {
+ return Arr::get($this->config, $key, $default);
+ }
+}
diff --git a/src/Drivers/Database.php b/src/Drivers/Database.php
new file mode 100644
index 0000000..0bc633a
--- /dev/null
+++ b/src/Drivers/Database.php
@@ -0,0 +1,125 @@
+database = app('db')->connection($this->config('connection'));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function create(array $params)
+ {
+ // Ensure the currency doesn't already exist
+ if ($this->find($params['code'], null) !== null) {
+ return 'exists';
+ }
+
+ // Created at stamp
+ $created = new DateTime('now');
+
+ $params = array_merge([
+ 'name' => '',
+ 'code' => '',
+ 'symbol' => '',
+ 'format' => '',
+ 'exchange_rate' => 1,
+ 'active' => 0,
+ 'created_at' => $created,
+ 'updated_at' => $created,
+ ], $params);
+
+ return $this->database->table($this->config('table'))->insert($params);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function all()
+ {
+ $collection = new Collection($this->database->table($this->config('table'))->get());
+
+ return $collection->keyBy('code')
+ ->map(function ($item) {
+ return [
+ 'id' => $item->id,
+ 'name' => $item->name,
+ 'code' => strtoupper($item->code),
+ 'symbol' => $item->symbol,
+ 'format' => $item->format,
+ 'exchange_rate' => $item->exchange_rate,
+ 'active' => $item->active,
+ 'created_at' => $item->updated_at,
+ 'updated_at' => $item->updated_at,
+ ];
+ })
+ ->all();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function find($code, $active = 1)
+ {
+ $query = $this->database->table($this->config('table'))
+ ->where('code', strtoupper($code));
+
+ // Make active optional
+ if (is_null($active) === false) {
+ $query->where('active', $active);
+ }
+
+ return $query->first();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update($code, array $attributes, DateTime $timestamp = null)
+ {
+ $table = $this->config('table');
+
+ // Create timestamp
+ if (empty($attributes['updated_at']) === true) {
+ $attributes['updated_at'] = new DateTime('now');
+ }
+
+ return $this->database->table($table)
+ ->where('code', strtoupper($code))
+ ->update($attributes);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete($code)
+ {
+ $table = $this->config('table');
+
+ return $this->database->table($table)
+ ->where('code', strtoupper($code))
+ ->delete();
+ }
+}
diff --git a/src/Drivers/Filesystem.php b/src/Drivers/Filesystem.php
new file mode 100644
index 0000000..1165b38
--- /dev/null
+++ b/src/Drivers/Filesystem.php
@@ -0,0 +1,142 @@
+filesystem = app('filesystem')->disk($this->config('disk'));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function create(array $params)
+ {
+ // Get blacklist path
+ $path = $this->config('path');
+
+ // Get all as an array
+ $currencies = $this->all();
+
+ // Verify the currency doesn't exists
+ if (isset($currencies[$params['code']]) === true) {
+ return 'exists';
+ }
+
+ // Created at stamp
+ $created = (new DateTime('now'))->format('Y-m-d H:i:s');
+
+ $currencies[$params['code']] = array_merge([
+ 'name' => '',
+ 'code' => '',
+ 'symbol' => '',
+ 'format' => '',
+ 'exchange_rate' => 1,
+ 'active' => 0,
+ 'created_at' => $created,
+ 'updated_at' => $created,
+ ], $params);
+
+ return $this->filesystem->put($path, json_encode($currencies, JSON_PRETTY_PRINT));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function all()
+ {
+ // Get blacklist path
+ $path = $this->config('path');
+
+ // Get contents if file exists
+ $contents = $this->filesystem->exists($path)
+ ? $this->filesystem->get($path)
+ : "{}";
+
+ return json_decode($contents, true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function find($code, $active = 1)
+ {
+ $currency = Arr::get($this->all(), $code);
+
+ // Skip active check
+ if (is_null($active)) {
+ return $currency;
+ }
+
+ return Arr::get($currency, 'active', 1) ? $currency : null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update($code, array $attributes, DateTime $timestamp = null)
+ {
+ // Get blacklist path
+ $path = $this->config('path');
+
+ // Get all as an array
+ $currencies = $this->all();
+
+ // Verify the currency exists
+ if (isset($currencies[$code]) === false) {
+ return 'doesn\'t exists';
+ }
+
+ // Create timestamp
+ if (empty($attributes['updated_at']) === true) {
+ $attributes['updated_at'] = (new DateTime('now'))->format('Y-m-d H:i:s');
+ }
+
+ // Merge values
+ $currencies[$code] = array_merge($currencies[$code], $attributes);
+
+ return $this->filesystem->put($path, json_encode($currencies, JSON_PRETTY_PRINT));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete($code)
+ {
+ // Get blacklist path
+ $path = $this->config('path');
+
+ // Get all as an array
+ $currencies = $this->all();
+
+ // Verify the currency exists
+ if (isset($currencies[$code]) === false) {
+ return false;
+ }
+
+ unset($currencies[$code]);
+
+ return $this->filesystem->put($path, json_encode($currencies, JSON_PRETTY_PRINT));
+ }
+}
diff --git a/src/Facades/Currency.php b/src/Facades/Currency.php
new file mode 100644
index 0000000..4d40e06
--- /dev/null
+++ b/src/Facades/Currency.php
@@ -0,0 +1,18 @@
+formatter = new NumberFormatter(config('app.locale'), NumberFormatter::CURRENCY);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function format($value, $code = null)
+ {
+ return $this->formatter->formatCurrency($value, $code);
+ }
+}
diff --git a/src/Middleware/CurrencyMiddleware.php b/src/Middleware/CurrencyMiddleware.php
new file mode 100644
index 0000000..d05185d
--- /dev/null
+++ b/src/Middleware/CurrencyMiddleware.php
@@ -0,0 +1,100 @@
+runningInConsole()) {
+ return $next($request);
+ }
+
+ // Check for a user defined currency
+ if (($currency = $this->getUserCurrency($request)) === null) {
+ $currency = $this->getDefaultCurrency();
+ }
+
+ // Set user currency
+ $this->setUserCurrency($currency, $request);
+
+ return $next($request);
+ }
+
+ /**
+ * Get the user selected currency.
+ *
+ * @param Request $request
+ *
+ * @return string|null
+ */
+ protected function getUserCurrency(Request $request)
+ {
+ // Check request for currency
+ $currency = $request->get('currency');
+ if ($currency && currency()->isActive($currency) === true) {
+ return $currency;
+ }
+
+ // Get currency from session
+ $currency = $request->getSession()->get('currency');
+ if ($currency && currency()->isActive($currency) === true) {
+ return $currency;
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the application default currency.
+ *
+ * @return string
+ */
+ protected function getDefaultCurrency()
+ {
+ return currency()->config('default');
+ }
+
+ /**
+ * Determine if the application is running in the console.
+ *
+ * @return bool
+ */
+ private function runningInConsole()
+ {
+ return app()->runningInConsole();
+ }
+
+ /**
+ * Set the user currency.
+ *
+ * @param string $currency
+ * @param Request $request
+ *
+ * @return string
+ */
+ private function setUserCurrency($currency, $request)
+ {
+ $currency = strtoupper($currency);
+
+ // Set user selection globally
+ currency()->setUserCurrency($currency);
+
+ // Save it for later too!
+ $request->getSession()->put(['currency' => $currency]);
+
+ return $currency;
+ }
+}
diff --git a/src/helpers.php b/src/helpers.php
new file mode 100644
index 0000000..8009aca
--- /dev/null
+++ b/src/helpers.php
@@ -0,0 +1,38 @@
+convert($amount, $from, $to, $format);
+ }
+}
+
+if (!function_exists('currency_format')) {
+ /**
+ * Format given number.
+ *
+ * @param float $amount
+ * @param string $currency
+ * @param bool $include_symbol
+ *
+ * @return string
+ */
+ function currency_format($amount = null, $currency = null, $include_symbol = true)
+ {
+ return app('currency')->format($amount, $currency, $include_symbol);
+ }
+}
diff --git a/tests/.gitkeep b/tests/.gitkeep
new file mode 100644
index 0000000..e69de29