├── LICENSE.md ├── README.md ├── composer.json ├── composer.lock ├── renovate.json └── src ├── DriverFactory.php ├── Drivers ├── BaseCurrencyDriver.php ├── CurrencyDriverContract.php ├── CurrencyLayer.php ├── ExchangeRatesApi.php ├── FixerIo.php ├── MockCurrencyDriver.php └── OpenExchangeRates.php ├── Exceptions ├── ApiException.php ├── CurrencyException.php └── DriverNotFoundException.php ├── Helpers └── DateHelper.php ├── Results └── ConversionResult.php └── Symbol.php /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © 2019–2024 [Alexansder Graf](https://github.com/otherguy/) 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 💱 Wrapper for popular Currency Exchange Rate APIs 2 | 3 | _A PHP API Wrapper to offer a unified programming interface for popular Currency Rate APIs._ 4 | 5 | [![Version](https://img.shields.io/packagist/v/otherguy/php-currency-api.svg?style=flat-square)](https://packagist.org/packages/otherguy/php-currency-api) 6 | [![Installs](https://img.shields.io/packagist/dt/otherguy/php-currency-api?color=blue&label=installs&style=flat-square)](https://packagist.org/packages/otherguy/php-currency-api) 7 | [![PHP version](https://img.shields.io/packagist/php-v/otherguy/php-currency-api?style=flat-square)](https://packagist.org/packages/otherguy/php-currency-api) 8 | [![Travis CI](https://img.shields.io/travis/com/otherguy/php-currency-api.svg?style=flat-square)](https://travis-ci.com/otherguy/php-currency-api) 9 | [![Coverage](https://img.shields.io/coveralls/otherguy/php-currency-api.svg?style=flat-square)](https://coveralls.io/github/otherguy/php-currency-api?branch=master) 10 | [![Coverage](https://img.shields.io/codeclimate/coverage-letter/otherguy/php-currency-api.svg?style=flat-square)](https://codeclimate.com/github/otherguy/php-currency-api) 11 | [![Maintainability](https://img.shields.io/codeclimate/maintainability/otherguy/php-currency-api.svg?style=flat-square)](https://codeclimate.com/github/otherguy/php-currency-api) 12 | [![License](https://img.shields.io/github/license/otherguy/php-currency-api.svg?style=flat-square&color=orange)](LICENSE.md) 13 | 14 | Dont worry about your favorite currency conversion service suddenly shutting down or switching plans on you. Switch away easily, without changing your code. 15 | 16 | ## Inspiration 💅 17 | 18 | I needed a currency conversion API for my travel website but could not find a good PHP package. The idea of the 19 | [`Rackbeat/php-currency-api`](https://github.com/Rackbeat/php-currency-api) package came closest but unfortunately it 20 | was just a stub and not implemented. 21 | 22 | ## Features 🌈 23 | 24 | * Support for [multiple different APIs](#supported-apis-) through the use of drivers 25 | * A [fluent interface](#fluent-interface) to make retrieving exchange rates convenient and fast 26 | * Consistent return interface that is independent of the driver being used 27 | * [Calculations](#conversion-result) can be made based on the returned data 28 | 29 | ## Supported APIs 🌐 30 | 31 | | Service | Identifier | 32 | |------------------------------------------------------|---------------------| 33 | | [FixerIO](https://fixer.io) | `fixerio` | 34 | | [CurrencyLayer](https://currencylayer.com) | `currencylayer` | 35 | | [Open Exchange Rates](https://openexchangerates.org) | `openexchangerates` | 36 | | [Exchange Rates API](https://exchangeratesapi.io) | `exchangeratesapi` | 37 | 38 | _If you want to see more services added, feel free to [open an issue](https://github.com/otherguy/php-currency-api/issues)!_ 39 | 40 | ## Prerequisites 📚 41 | 42 | * `PHP 8.x` or `PHP 7.3+` or higher (tested on both `7.3` and `7.4`) 43 | * The [`composer`](https://getcomposer.org) dependency manager for PHP 44 | * An account with one or more of the [API providers](#supported-apis-) listed above 45 | 46 | ## Installation 🚀 47 | 48 | Simply require the package using `composer` and you're good to go! 49 | 50 | ```bash 51 | $ composer require otherguy/php-currency-api 52 | ``` 53 | 54 | ## Usage 🛠 55 | 56 | ### Currency Symbol Helper 57 | 58 | The [`Otherguy\Currency\Symbol`](src/Symbol.php) class provides constants for each supported currency. 59 | 60 | > !**Note:** You are not required to use `Otherguy\Currency\Symbol` to specify symbols. It's simply a convenience helper 61 | > and does not need to be used. You can simply pass strings like `'USD', 'EUR', ...` to all methods. 62 | 63 | ```php 64 | // 'USD' 65 | $symbol = Otherguy\Currency\Symbol::USD; 66 | ``` 67 | 68 | Use the `all()` method to retrieve an array of all currency symbols: 69 | 70 | ```php 71 | // [ 'AED', 'AFN', ... 'ZWL' ] 72 | $symbols = Otherguy\Currency\Symbol::all(); 73 | ``` 74 | 75 | The `names()` method returns an associative array with currency names instead: 76 | 77 | ```php 78 | // [ 'AED' => 'United Arab Emirates Dirham', 'AFN' => 'Afghan Afghani', ... ] 79 | $symbols = Otherguy\Currency\Symbol::names(); 80 | ``` 81 | 82 | To get the name of a single currency, use the `name()` method: 83 | 84 | ```php 85 | // 'United States Dollar' 86 | $symbols = Otherguy\Currency\Symbol::name(Otherguy\Currency\Symbol::USD); 87 | ``` 88 | 89 | ### Initialize API Instance 90 | 91 | ```php 92 | $currency = Otherguy\Currency\DriverFactory::make('fixerio'); // driver identifier from supported drivers. 93 | ``` 94 | 95 | To get a list of supported drivers, use the `getDrivers()` method: 96 | 97 | ```php 98 | // [ 'mock', 'fixerio', 'currencylayer', ... ] 99 | $drivers = Otherguy\Currency\DriverFactory::getDrivers() 100 | ``` 101 | 102 | ### Set Access Key 103 | 104 | Most API providers require you to sign up and use your issued access key to authenticate against their API. You can 105 | specify your access key like so: 106 | 107 | ```php 108 | $currency->accessKey('your-access-token-goes-here'); 109 | ``` 110 | 111 | ### Set Configuration Options 112 | 113 | To set further configuration options, you can use the `config()` method. An example is 114 | [CurrencyLayer's JSON formatting option](https://currencylayer.com/documentation#format). 115 | 116 | ```php 117 | $currency->config('format', '1'); 118 | ``` 119 | 120 | ### Set Base Currency 121 | 122 | You can use either `from()` or `source()` to set the base currency. The methods are identical. 123 | 124 | > !**Note:** Each driver sets its own default base currency. [FixerIO](https://fixer.io) uses `EUR` as base currency 125 | > while [CurrencyLayer](https://currencylayer.com) uses `USD`. 126 | 127 | Most services only allow you to change the base currency in their paid plans. The driver will throw a 128 | `Otherguy\Currency\Exceptions\ApiException` if your current plan does not allow changing the base currency. 129 | 130 | ```php 131 | $currency->source(Otherguy\Currency\Symbol::USD); 132 | $currency->from(Otherguy\Currency\Symbol::USD); 133 | ``` 134 | 135 | ### Set Return Currencies 136 | 137 | You can use either `to()` or `symbols()` to set the return currencies. The methods are identical. Pass a single currency 138 | or an array of currency symbols to either of these methods. 139 | 140 | > !**Note:** Pass an empty array to return all currency symbols supported by this driver. This is the default if you 141 | > don't call the method at all. 142 | 143 | ```php 144 | $currency->to(Otherguy\Currency\Symbol::BTC); 145 | $currency->symbols([Otherguy\Currency\Symbol::BTC, Otherguy\Currency\Symbol::EUR, Otherguy\Currency\Symbol::USD]); 146 | ``` 147 | 148 | ### Latest Rates 149 | 150 | This retrieves the most recent exchange rates and returns a [`ConversionResult`](#conversion-result) object. 151 | 152 | ```php 153 | $currency->get(); // Get latest rates for selected symbols, using set base currency 154 | $currency->get('DKK'); // Get latest rates for selected symbols, using DKK as base currency 155 | ``` 156 | 157 | ### Historical Rates 158 | 159 | To retrieve historical exchange rates, use the `historical()` method. Note that you need to specify a date either as a 160 | method parameter or by using the `date()` methods. See [Fluent Interface](#fluent-interface) for more information. 161 | 162 | ```php 163 | $currency->date('2010-01-01')->historical(); 164 | $currency->historical('2018-07-01'); 165 | ``` 166 | 167 | ### Convert Amount 168 | 169 | Use the `convert()` method to convert amounts between currencies. 170 | 171 | > !**Note:** Most API providers don't allow access to this method using your free account. You can still use the 172 | > [Latest Rates](#latest-rates) or [Historical Rates](#historical-rates) endpoints and perform calculations or conversions 173 | > on the [`ConversionResult`](#conversion-result) object. 174 | 175 | ```php 176 | $currency->convert(10.00, 'USD', 'THB'); // Convert 10 USD to THB 177 | $currency->convert(122.50, 'NPR', 'EUR', '2019-01-01'); // Convert 122.50 NPR to EUR using the rates from January 1st, 2019 178 | ``` 179 | 180 | ### Fluent Interface 181 | 182 | Most methods can be used with a _fluent interface_, allowing you to chain method calls for more readable code: 183 | 184 | ```php 185 | // Namespaces are omitted for readability! 186 | DriverFactory::make('driver')->from(Symbol::USD)->to(Symbol::EUR)->get(); 187 | DriverFactory::make('driver')->from(Symbol::USD)->to(Symbol::NPR)->date('2013-03-02')->historical(); 188 | DriverFactory::make('driver')->from(Symbol::USD)->to(Symbol::NPR)->amount(12.10)->convert(); 189 | ``` 190 | 191 | ### Conversion Result 192 | 193 | The [`get()`](#latest-rates) and [`historical()`](#historical-rates) endpoints return a 194 | [`ConversionResult`](src/Results/ConversionResult.php) object. This object allows you to perform calculations and 195 | conversions easily. 196 | 197 | > !**Note:** Even though free accounts of most providers do not allow you to change the base currency, you can still 198 | > use the `ConversionResult` object to change the base currency later. This might not be as accurate as changing the 199 | > base currency directly, though. 200 | 201 | > !**Note:** To convert between two currencies, you need to request both of them in your initial [`get()`](#latest-rates) 202 | > or [`historical()`](#historical-rates) request. You can not convert between currencies that have not been fetched! 203 | 204 | See the following code for some examples of what you can do with the `ConversionResult` object. 205 | 206 | ```php 207 | $result = DriverFactory::make('driver')->from(Symbol::USD)->to([Symbol::EUR, Symbol::GBP])->get(); 208 | 209 | // [ 'USD' => 1.00, 'EUR' => 0.89, 'GBP' => 0.79 ] 210 | $result->all(); 211 | 212 | // 'USD' 213 | $result->getBaseCurrency(); 214 | 215 | // '2019-06-11' 216 | $result->getDate(); 217 | 218 | // 0.89 219 | $result->rate(Symbol::EUR); 220 | 221 | // CurrencyException("No conversion result for BTC!"); 222 | $result->rate(Symbol::BTC); 223 | 224 | // 5.618 225 | $result->convert(5.0, Symbol::EUR, Symbol::USD); 226 | 227 | // [ 'USD' => 1.13, 'EUR' => 1.00, 'GBP' => 0.89 ] 228 | $result->setBaseCurrency(Symbol::EUR)->all(); 229 | 230 | // 1.12 231 | $result->setBaseCurrency(Symbol::GBP)->rate(Symbol::EUR); 232 | ``` 233 | 234 | ## Contributing 🚧 235 | 236 | [Pull Requests](https://github.com/otherguy/php-currency-api/pulls) are more than welcome! I'm striving for 100% test 237 | coverage for this repository so please make sure to add tests for your code. 238 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "otherguy/php-currency-api", 3 | "description": "A PHP API Wrapper to offer a unified programming interface for popular Currency Rate APIs.", 4 | "keywords": [ 5 | "currency", 6 | "currency rates", 7 | "exchange rates", 8 | "currency conversion", 9 | "currency", 10 | "currency-exchange-rates", 11 | "composer-package", 12 | "php-library", 13 | "currency-converter-php", 14 | "currency-api", 15 | "exchange-rates", 16 | "currency-rate-apis", 17 | "fluent-interface", 18 | "api-wrapper", 19 | "currency-converter", 20 | "currency-conversion", 21 | "currency-exchange", 22 | "exchange-rate-api", 23 | "exchange-rates-api", 24 | "php-package", 25 | "php8", 26 | "php74", 27 | "php73" 28 | ], 29 | "type": "library", 30 | "license": "MIT", 31 | "authors": [ 32 | { 33 | "name": "Alexander Graf", 34 | "email": "alex@otherguy.io" 35 | } 36 | ], 37 | "require": { 38 | "php": ">=7.3", 39 | "ext-json": "*", 40 | "guzzlehttp/guzzle": "^7.2" 41 | }, 42 | "require-dev": { 43 | "nikic/php-parser": "^4.10", 44 | "php-coveralls/php-coveralls": "^2.4", 45 | "phpunit/php-code-coverage": "^9.2", 46 | "phpunit/phpunit": "^9.4" 47 | }, 48 | "suggest": { 49 | "ext-curl": "Faster HTTP requests" 50 | }, 51 | "autoload": { 52 | "psr-4": { 53 | "Otherguy\\Currency\\": "src/" 54 | } 55 | }, 56 | "autoload-dev": { 57 | "psr-4": { 58 | "Currency\\Tests\\": "tests/" 59 | } 60 | }, 61 | "config": { 62 | "sort-packages": true 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "271a92e359371033df60fa8d63e37268", 8 | "packages": [ 9 | { 10 | "name": "guzzlehttp/guzzle", 11 | "version": "7.8.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/guzzle/guzzle.git", 15 | "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", 20 | "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "ext-json": "*", 25 | "guzzlehttp/promises": "^1.5.3 || ^2.0.1", 26 | "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", 27 | "php": "^7.2.5 || ^8.0", 28 | "psr/http-client": "^1.0", 29 | "symfony/deprecation-contracts": "^2.2 || ^3.0" 30 | }, 31 | "provide": { 32 | "psr/http-client-implementation": "1.0" 33 | }, 34 | "require-dev": { 35 | "bamarni/composer-bin-plugin": "^1.8.2", 36 | "ext-curl": "*", 37 | "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", 38 | "php-http/message-factory": "^1.1", 39 | "phpunit/phpunit": "^8.5.36 || ^9.6.15", 40 | "psr/log": "^1.1 || ^2.0 || ^3.0" 41 | }, 42 | "suggest": { 43 | "ext-curl": "Required for CURL handler support", 44 | "ext-intl": "Required for Internationalized Domain Name (IDN) support", 45 | "psr/log": "Required for using the Log middleware" 46 | }, 47 | "type": "library", 48 | "extra": { 49 | "bamarni-bin": { 50 | "bin-links": true, 51 | "forward-command": false 52 | } 53 | }, 54 | "autoload": { 55 | "files": [ 56 | "src/functions_include.php" 57 | ], 58 | "psr-4": { 59 | "GuzzleHttp\\": "src/" 60 | } 61 | }, 62 | "notification-url": "https://packagist.org/downloads/", 63 | "license": [ 64 | "MIT" 65 | ], 66 | "authors": [ 67 | { 68 | "name": "Graham Campbell", 69 | "email": "hello@gjcampbell.co.uk", 70 | "homepage": "https://github.com/GrahamCampbell" 71 | }, 72 | { 73 | "name": "Michael Dowling", 74 | "email": "mtdowling@gmail.com", 75 | "homepage": "https://github.com/mtdowling" 76 | }, 77 | { 78 | "name": "Jeremy Lindblom", 79 | "email": "jeremeamia@gmail.com", 80 | "homepage": "https://github.com/jeremeamia" 81 | }, 82 | { 83 | "name": "George Mponos", 84 | "email": "gmponos@gmail.com", 85 | "homepage": "https://github.com/gmponos" 86 | }, 87 | { 88 | "name": "Tobias Nyholm", 89 | "email": "tobias.nyholm@gmail.com", 90 | "homepage": "https://github.com/Nyholm" 91 | }, 92 | { 93 | "name": "Márk Sági-Kazár", 94 | "email": "mark.sagikazar@gmail.com", 95 | "homepage": "https://github.com/sagikazarmark" 96 | }, 97 | { 98 | "name": "Tobias Schultze", 99 | "email": "webmaster@tubo-world.de", 100 | "homepage": "https://github.com/Tobion" 101 | } 102 | ], 103 | "description": "Guzzle is a PHP HTTP client library", 104 | "keywords": [ 105 | "client", 106 | "curl", 107 | "framework", 108 | "http", 109 | "http client", 110 | "psr-18", 111 | "psr-7", 112 | "rest", 113 | "web service" 114 | ], 115 | "funding": [ 116 | { 117 | "url": "https://github.com/GrahamCampbell", 118 | "type": "github" 119 | }, 120 | { 121 | "url": "https://github.com/Nyholm", 122 | "type": "github" 123 | }, 124 | { 125 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", 126 | "type": "tidelift" 127 | } 128 | ], 129 | "time": "2023-12-03T20:35:24+00:00" 130 | }, 131 | { 132 | "name": "guzzlehttp/promises", 133 | "version": "2.0.2", 134 | "source": { 135 | "type": "git", 136 | "url": "https://github.com/guzzle/promises.git", 137 | "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" 138 | }, 139 | "dist": { 140 | "type": "zip", 141 | "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", 142 | "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", 143 | "shasum": "" 144 | }, 145 | "require": { 146 | "php": "^7.2.5 || ^8.0" 147 | }, 148 | "require-dev": { 149 | "bamarni/composer-bin-plugin": "^1.8.2", 150 | "phpunit/phpunit": "^8.5.36 || ^9.6.15" 151 | }, 152 | "type": "library", 153 | "extra": { 154 | "bamarni-bin": { 155 | "bin-links": true, 156 | "forward-command": false 157 | } 158 | }, 159 | "autoload": { 160 | "psr-4": { 161 | "GuzzleHttp\\Promise\\": "src/" 162 | } 163 | }, 164 | "notification-url": "https://packagist.org/downloads/", 165 | "license": [ 166 | "MIT" 167 | ], 168 | "authors": [ 169 | { 170 | "name": "Graham Campbell", 171 | "email": "hello@gjcampbell.co.uk", 172 | "homepage": "https://github.com/GrahamCampbell" 173 | }, 174 | { 175 | "name": "Michael Dowling", 176 | "email": "mtdowling@gmail.com", 177 | "homepage": "https://github.com/mtdowling" 178 | }, 179 | { 180 | "name": "Tobias Nyholm", 181 | "email": "tobias.nyholm@gmail.com", 182 | "homepage": "https://github.com/Nyholm" 183 | }, 184 | { 185 | "name": "Tobias Schultze", 186 | "email": "webmaster@tubo-world.de", 187 | "homepage": "https://github.com/Tobion" 188 | } 189 | ], 190 | "description": "Guzzle promises library", 191 | "keywords": [ 192 | "promise" 193 | ], 194 | "funding": [ 195 | { 196 | "url": "https://github.com/GrahamCampbell", 197 | "type": "github" 198 | }, 199 | { 200 | "url": "https://github.com/Nyholm", 201 | "type": "github" 202 | }, 203 | { 204 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", 205 | "type": "tidelift" 206 | } 207 | ], 208 | "time": "2023-12-03T20:19:20+00:00" 209 | }, 210 | { 211 | "name": "guzzlehttp/psr7", 212 | "version": "2.6.2", 213 | "source": { 214 | "type": "git", 215 | "url": "https://github.com/guzzle/psr7.git", 216 | "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" 217 | }, 218 | "dist": { 219 | "type": "zip", 220 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", 221 | "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", 222 | "shasum": "" 223 | }, 224 | "require": { 225 | "php": "^7.2.5 || ^8.0", 226 | "psr/http-factory": "^1.0", 227 | "psr/http-message": "^1.1 || ^2.0", 228 | "ralouphie/getallheaders": "^3.0" 229 | }, 230 | "provide": { 231 | "psr/http-factory-implementation": "1.0", 232 | "psr/http-message-implementation": "1.0" 233 | }, 234 | "require-dev": { 235 | "bamarni/composer-bin-plugin": "^1.8.2", 236 | "http-interop/http-factory-tests": "^0.9", 237 | "phpunit/phpunit": "^8.5.36 || ^9.6.15" 238 | }, 239 | "suggest": { 240 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" 241 | }, 242 | "type": "library", 243 | "extra": { 244 | "bamarni-bin": { 245 | "bin-links": true, 246 | "forward-command": false 247 | } 248 | }, 249 | "autoload": { 250 | "psr-4": { 251 | "GuzzleHttp\\Psr7\\": "src/" 252 | } 253 | }, 254 | "notification-url": "https://packagist.org/downloads/", 255 | "license": [ 256 | "MIT" 257 | ], 258 | "authors": [ 259 | { 260 | "name": "Graham Campbell", 261 | "email": "hello@gjcampbell.co.uk", 262 | "homepage": "https://github.com/GrahamCampbell" 263 | }, 264 | { 265 | "name": "Michael Dowling", 266 | "email": "mtdowling@gmail.com", 267 | "homepage": "https://github.com/mtdowling" 268 | }, 269 | { 270 | "name": "George Mponos", 271 | "email": "gmponos@gmail.com", 272 | "homepage": "https://github.com/gmponos" 273 | }, 274 | { 275 | "name": "Tobias Nyholm", 276 | "email": "tobias.nyholm@gmail.com", 277 | "homepage": "https://github.com/Nyholm" 278 | }, 279 | { 280 | "name": "Márk Sági-Kazár", 281 | "email": "mark.sagikazar@gmail.com", 282 | "homepage": "https://github.com/sagikazarmark" 283 | }, 284 | { 285 | "name": "Tobias Schultze", 286 | "email": "webmaster@tubo-world.de", 287 | "homepage": "https://github.com/Tobion" 288 | }, 289 | { 290 | "name": "Márk Sági-Kazár", 291 | "email": "mark.sagikazar@gmail.com", 292 | "homepage": "https://sagikazarmark.hu" 293 | } 294 | ], 295 | "description": "PSR-7 message implementation that also provides common utility methods", 296 | "keywords": [ 297 | "http", 298 | "message", 299 | "psr-7", 300 | "request", 301 | "response", 302 | "stream", 303 | "uri", 304 | "url" 305 | ], 306 | "funding": [ 307 | { 308 | "url": "https://github.com/GrahamCampbell", 309 | "type": "github" 310 | }, 311 | { 312 | "url": "https://github.com/Nyholm", 313 | "type": "github" 314 | }, 315 | { 316 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", 317 | "type": "tidelift" 318 | } 319 | ], 320 | "time": "2023-12-03T20:05:35+00:00" 321 | }, 322 | { 323 | "name": "psr/http-client", 324 | "version": "1.0.3", 325 | "source": { 326 | "type": "git", 327 | "url": "https://github.com/php-fig/http-client.git", 328 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" 329 | }, 330 | "dist": { 331 | "type": "zip", 332 | "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", 333 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", 334 | "shasum": "" 335 | }, 336 | "require": { 337 | "php": "^7.0 || ^8.0", 338 | "psr/http-message": "^1.0 || ^2.0" 339 | }, 340 | "type": "library", 341 | "extra": { 342 | "branch-alias": { 343 | "dev-master": "1.0.x-dev" 344 | } 345 | }, 346 | "autoload": { 347 | "psr-4": { 348 | "Psr\\Http\\Client\\": "src/" 349 | } 350 | }, 351 | "notification-url": "https://packagist.org/downloads/", 352 | "license": [ 353 | "MIT" 354 | ], 355 | "authors": [ 356 | { 357 | "name": "PHP-FIG", 358 | "homepage": "https://www.php-fig.org/" 359 | } 360 | ], 361 | "description": "Common interface for HTTP clients", 362 | "homepage": "https://github.com/php-fig/http-client", 363 | "keywords": [ 364 | "http", 365 | "http-client", 366 | "psr", 367 | "psr-18" 368 | ], 369 | "time": "2023-09-23T14:17:50+00:00" 370 | }, 371 | { 372 | "name": "psr/http-factory", 373 | "version": "1.0.2", 374 | "source": { 375 | "type": "git", 376 | "url": "https://github.com/php-fig/http-factory.git", 377 | "reference": "e616d01114759c4c489f93b099585439f795fe35" 378 | }, 379 | "dist": { 380 | "type": "zip", 381 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", 382 | "reference": "e616d01114759c4c489f93b099585439f795fe35", 383 | "shasum": "" 384 | }, 385 | "require": { 386 | "php": ">=7.0.0", 387 | "psr/http-message": "^1.0 || ^2.0" 388 | }, 389 | "type": "library", 390 | "extra": { 391 | "branch-alias": { 392 | "dev-master": "1.0.x-dev" 393 | } 394 | }, 395 | "autoload": { 396 | "psr-4": { 397 | "Psr\\Http\\Message\\": "src/" 398 | } 399 | }, 400 | "notification-url": "https://packagist.org/downloads/", 401 | "license": [ 402 | "MIT" 403 | ], 404 | "authors": [ 405 | { 406 | "name": "PHP-FIG", 407 | "homepage": "https://www.php-fig.org/" 408 | } 409 | ], 410 | "description": "Common interfaces for PSR-7 HTTP message factories", 411 | "keywords": [ 412 | "factory", 413 | "http", 414 | "message", 415 | "psr", 416 | "psr-17", 417 | "psr-7", 418 | "request", 419 | "response" 420 | ], 421 | "time": "2023-04-10T20:10:41+00:00" 422 | }, 423 | { 424 | "name": "psr/http-message", 425 | "version": "2.0", 426 | "source": { 427 | "type": "git", 428 | "url": "https://github.com/php-fig/http-message.git", 429 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" 430 | }, 431 | "dist": { 432 | "type": "zip", 433 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", 434 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", 435 | "shasum": "" 436 | }, 437 | "require": { 438 | "php": "^7.2 || ^8.0" 439 | }, 440 | "type": "library", 441 | "extra": { 442 | "branch-alias": { 443 | "dev-master": "2.0.x-dev" 444 | } 445 | }, 446 | "autoload": { 447 | "psr-4": { 448 | "Psr\\Http\\Message\\": "src/" 449 | } 450 | }, 451 | "notification-url": "https://packagist.org/downloads/", 452 | "license": [ 453 | "MIT" 454 | ], 455 | "authors": [ 456 | { 457 | "name": "PHP-FIG", 458 | "homepage": "https://www.php-fig.org/" 459 | } 460 | ], 461 | "description": "Common interface for HTTP messages", 462 | "homepage": "https://github.com/php-fig/http-message", 463 | "keywords": [ 464 | "http", 465 | "http-message", 466 | "psr", 467 | "psr-7", 468 | "request", 469 | "response" 470 | ], 471 | "time": "2023-04-04T09:54:51+00:00" 472 | }, 473 | { 474 | "name": "ralouphie/getallheaders", 475 | "version": "3.0.3", 476 | "source": { 477 | "type": "git", 478 | "url": "https://github.com/ralouphie/getallheaders.git", 479 | "reference": "120b605dfeb996808c31b6477290a714d356e822" 480 | }, 481 | "dist": { 482 | "type": "zip", 483 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", 484 | "reference": "120b605dfeb996808c31b6477290a714d356e822", 485 | "shasum": "" 486 | }, 487 | "require": { 488 | "php": ">=5.6" 489 | }, 490 | "require-dev": { 491 | "php-coveralls/php-coveralls": "^2.1", 492 | "phpunit/phpunit": "^5 || ^6.5" 493 | }, 494 | "type": "library", 495 | "autoload": { 496 | "files": [ 497 | "src/getallheaders.php" 498 | ] 499 | }, 500 | "notification-url": "https://packagist.org/downloads/", 501 | "license": [ 502 | "MIT" 503 | ], 504 | "authors": [ 505 | { 506 | "name": "Ralph Khattar", 507 | "email": "ralph.khattar@gmail.com" 508 | } 509 | ], 510 | "description": "A polyfill for getallheaders.", 511 | "time": "2019-03-08T08:55:37+00:00" 512 | }, 513 | { 514 | "name": "symfony/deprecation-contracts", 515 | "version": "v2.5.2", 516 | "source": { 517 | "type": "git", 518 | "url": "https://github.com/symfony/deprecation-contracts.git", 519 | "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" 520 | }, 521 | "dist": { 522 | "type": "zip", 523 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", 524 | "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", 525 | "shasum": "" 526 | }, 527 | "require": { 528 | "php": ">=7.1" 529 | }, 530 | "type": "library", 531 | "extra": { 532 | "branch-alias": { 533 | "dev-main": "2.5-dev" 534 | }, 535 | "thanks": { 536 | "name": "symfony/contracts", 537 | "url": "https://github.com/symfony/contracts" 538 | } 539 | }, 540 | "autoload": { 541 | "files": [ 542 | "function.php" 543 | ] 544 | }, 545 | "notification-url": "https://packagist.org/downloads/", 546 | "license": [ 547 | "MIT" 548 | ], 549 | "authors": [ 550 | { 551 | "name": "Nicolas Grekas", 552 | "email": "p@tchwork.com" 553 | }, 554 | { 555 | "name": "Symfony Community", 556 | "homepage": "https://symfony.com/contributors" 557 | } 558 | ], 559 | "description": "A generic function and convention to trigger deprecation notices", 560 | "homepage": "https://symfony.com", 561 | "funding": [ 562 | { 563 | "url": "https://symfony.com/sponsor", 564 | "type": "custom" 565 | }, 566 | { 567 | "url": "https://github.com/fabpot", 568 | "type": "github" 569 | }, 570 | { 571 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 572 | "type": "tidelift" 573 | } 574 | ], 575 | "time": "2022-01-02T09:53:40+00:00" 576 | } 577 | ], 578 | "packages-dev": [ 579 | { 580 | "name": "doctrine/instantiator", 581 | "version": "1.5.0", 582 | "source": { 583 | "type": "git", 584 | "url": "https://github.com/doctrine/instantiator.git", 585 | "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" 586 | }, 587 | "dist": { 588 | "type": "zip", 589 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", 590 | "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", 591 | "shasum": "" 592 | }, 593 | "require": { 594 | "php": "^7.1 || ^8.0" 595 | }, 596 | "require-dev": { 597 | "doctrine/coding-standard": "^9 || ^11", 598 | "ext-pdo": "*", 599 | "ext-phar": "*", 600 | "phpbench/phpbench": "^0.16 || ^1", 601 | "phpstan/phpstan": "^1.4", 602 | "phpstan/phpstan-phpunit": "^1", 603 | "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", 604 | "vimeo/psalm": "^4.30 || ^5.4" 605 | }, 606 | "type": "library", 607 | "autoload": { 608 | "psr-4": { 609 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 610 | } 611 | }, 612 | "notification-url": "https://packagist.org/downloads/", 613 | "license": [ 614 | "MIT" 615 | ], 616 | "authors": [ 617 | { 618 | "name": "Marco Pivetta", 619 | "email": "ocramius@gmail.com", 620 | "homepage": "https://ocramius.github.io/" 621 | } 622 | ], 623 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 624 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 625 | "keywords": [ 626 | "constructor", 627 | "instantiate" 628 | ], 629 | "funding": [ 630 | { 631 | "url": "https://www.doctrine-project.org/sponsorship.html", 632 | "type": "custom" 633 | }, 634 | { 635 | "url": "https://www.patreon.com/phpdoctrine", 636 | "type": "patreon" 637 | }, 638 | { 639 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 640 | "type": "tidelift" 641 | } 642 | ], 643 | "time": "2022-12-30T00:15:36+00:00" 644 | }, 645 | { 646 | "name": "myclabs/deep-copy", 647 | "version": "1.11.1", 648 | "source": { 649 | "type": "git", 650 | "url": "https://github.com/myclabs/DeepCopy.git", 651 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" 652 | }, 653 | "dist": { 654 | "type": "zip", 655 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", 656 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", 657 | "shasum": "" 658 | }, 659 | "require": { 660 | "php": "^7.1 || ^8.0" 661 | }, 662 | "conflict": { 663 | "doctrine/collections": "<1.6.8", 664 | "doctrine/common": "<2.13.3 || >=3,<3.2.2" 665 | }, 666 | "require-dev": { 667 | "doctrine/collections": "^1.6.8", 668 | "doctrine/common": "^2.13.3 || ^3.2.2", 669 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 670 | }, 671 | "type": "library", 672 | "autoload": { 673 | "files": [ 674 | "src/DeepCopy/deep_copy.php" 675 | ], 676 | "psr-4": { 677 | "DeepCopy\\": "src/DeepCopy/" 678 | } 679 | }, 680 | "notification-url": "https://packagist.org/downloads/", 681 | "license": [ 682 | "MIT" 683 | ], 684 | "description": "Create deep copies (clones) of your objects", 685 | "keywords": [ 686 | "clone", 687 | "copy", 688 | "duplicate", 689 | "object", 690 | "object graph" 691 | ], 692 | "funding": [ 693 | { 694 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 695 | "type": "tidelift" 696 | } 697 | ], 698 | "time": "2023-03-08T13:26:56+00:00" 699 | }, 700 | { 701 | "name": "nikic/php-parser", 702 | "version": "v4.17.1", 703 | "source": { 704 | "type": "git", 705 | "url": "https://github.com/nikic/PHP-Parser.git", 706 | "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" 707 | }, 708 | "dist": { 709 | "type": "zip", 710 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", 711 | "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", 712 | "shasum": "" 713 | }, 714 | "require": { 715 | "ext-tokenizer": "*", 716 | "php": ">=7.0" 717 | }, 718 | "require-dev": { 719 | "ircmaxell/php-yacc": "^0.0.7", 720 | "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" 721 | }, 722 | "bin": [ 723 | "bin/php-parse" 724 | ], 725 | "type": "library", 726 | "extra": { 727 | "branch-alias": { 728 | "dev-master": "4.9-dev" 729 | } 730 | }, 731 | "autoload": { 732 | "psr-4": { 733 | "PhpParser\\": "lib/PhpParser" 734 | } 735 | }, 736 | "notification-url": "https://packagist.org/downloads/", 737 | "license": [ 738 | "BSD-3-Clause" 739 | ], 740 | "authors": [ 741 | { 742 | "name": "Nikita Popov" 743 | } 744 | ], 745 | "description": "A PHP parser written in PHP", 746 | "keywords": [ 747 | "parser", 748 | "php" 749 | ], 750 | "time": "2023-08-13T19:53:39+00:00" 751 | }, 752 | { 753 | "name": "phar-io/manifest", 754 | "version": "2.0.3", 755 | "source": { 756 | "type": "git", 757 | "url": "https://github.com/phar-io/manifest.git", 758 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53" 759 | }, 760 | "dist": { 761 | "type": "zip", 762 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", 763 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53", 764 | "shasum": "" 765 | }, 766 | "require": { 767 | "ext-dom": "*", 768 | "ext-phar": "*", 769 | "ext-xmlwriter": "*", 770 | "phar-io/version": "^3.0.1", 771 | "php": "^7.2 || ^8.0" 772 | }, 773 | "type": "library", 774 | "extra": { 775 | "branch-alias": { 776 | "dev-master": "2.0.x-dev" 777 | } 778 | }, 779 | "autoload": { 780 | "classmap": [ 781 | "src/" 782 | ] 783 | }, 784 | "notification-url": "https://packagist.org/downloads/", 785 | "license": [ 786 | "BSD-3-Clause" 787 | ], 788 | "authors": [ 789 | { 790 | "name": "Arne Blankerts", 791 | "email": "arne@blankerts.de", 792 | "role": "Developer" 793 | }, 794 | { 795 | "name": "Sebastian Heuer", 796 | "email": "sebastian@phpeople.de", 797 | "role": "Developer" 798 | }, 799 | { 800 | "name": "Sebastian Bergmann", 801 | "email": "sebastian@phpunit.de", 802 | "role": "Developer" 803 | } 804 | ], 805 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 806 | "time": "2021-07-20T11:28:43+00:00" 807 | }, 808 | { 809 | "name": "phar-io/version", 810 | "version": "3.2.1", 811 | "source": { 812 | "type": "git", 813 | "url": "https://github.com/phar-io/version.git", 814 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 815 | }, 816 | "dist": { 817 | "type": "zip", 818 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 819 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 820 | "shasum": "" 821 | }, 822 | "require": { 823 | "php": "^7.2 || ^8.0" 824 | }, 825 | "type": "library", 826 | "autoload": { 827 | "classmap": [ 828 | "src/" 829 | ] 830 | }, 831 | "notification-url": "https://packagist.org/downloads/", 832 | "license": [ 833 | "BSD-3-Clause" 834 | ], 835 | "authors": [ 836 | { 837 | "name": "Arne Blankerts", 838 | "email": "arne@blankerts.de", 839 | "role": "Developer" 840 | }, 841 | { 842 | "name": "Sebastian Heuer", 843 | "email": "sebastian@phpeople.de", 844 | "role": "Developer" 845 | }, 846 | { 847 | "name": "Sebastian Bergmann", 848 | "email": "sebastian@phpunit.de", 849 | "role": "Developer" 850 | } 851 | ], 852 | "description": "Library for handling version information and constraints", 853 | "time": "2022-02-21T01:04:05+00:00" 854 | }, 855 | { 856 | "name": "php-coveralls/php-coveralls", 857 | "version": "v2.7.0", 858 | "source": { 859 | "type": "git", 860 | "url": "https://github.com/php-coveralls/php-coveralls.git", 861 | "reference": "b36fa4394e519dafaddc04ae03976bc65a25ba15" 862 | }, 863 | "dist": { 864 | "type": "zip", 865 | "url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/b36fa4394e519dafaddc04ae03976bc65a25ba15", 866 | "reference": "b36fa4394e519dafaddc04ae03976bc65a25ba15", 867 | "shasum": "" 868 | }, 869 | "require": { 870 | "ext-json": "*", 871 | "ext-simplexml": "*", 872 | "guzzlehttp/guzzle": "^6.0 || ^7.0", 873 | "php": "^7.0 || ^8.0", 874 | "psr/log": "^1.0 || ^2.0", 875 | "symfony/config": "^2.1 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", 876 | "symfony/console": "^2.1 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", 877 | "symfony/stopwatch": "^2.0 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", 878 | "symfony/yaml": "^2.0.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0" 879 | }, 880 | "require-dev": { 881 | "phpunit/phpunit": "^4.8.35 || ^5.4.3 || ^6.0 || ^7.0 || >=8.0 <8.5.29 || >=9.0 <9.5.23", 882 | "sanmai/phpunit-legacy-adapter": "^6.1 || ^8.0" 883 | }, 884 | "suggest": { 885 | "symfony/http-kernel": "Allows Symfony integration" 886 | }, 887 | "bin": [ 888 | "bin/php-coveralls" 889 | ], 890 | "type": "library", 891 | "autoload": { 892 | "psr-4": { 893 | "PhpCoveralls\\": "src/" 894 | } 895 | }, 896 | "notification-url": "https://packagist.org/downloads/", 897 | "license": [ 898 | "MIT" 899 | ], 900 | "authors": [ 901 | { 902 | "name": "Kitamura Satoshi", 903 | "email": "with.no.parachute@gmail.com", 904 | "homepage": "https://www.facebook.com/satooshi.jp", 905 | "role": "Original creator" 906 | }, 907 | { 908 | "name": "Takashi Matsuo", 909 | "email": "tmatsuo@google.com" 910 | }, 911 | { 912 | "name": "Google Inc" 913 | }, 914 | { 915 | "name": "Dariusz Ruminski", 916 | "email": "dariusz.ruminski@gmail.com", 917 | "homepage": "https://github.com/keradus" 918 | }, 919 | { 920 | "name": "Contributors", 921 | "homepage": "https://github.com/php-coveralls/php-coveralls/graphs/contributors" 922 | } 923 | ], 924 | "description": "PHP client library for Coveralls API", 925 | "homepage": "https://github.com/php-coveralls/php-coveralls", 926 | "keywords": [ 927 | "ci", 928 | "coverage", 929 | "github", 930 | "test" 931 | ], 932 | "time": "2023-11-22T10:21:01+00:00" 933 | }, 934 | { 935 | "name": "phpunit/php-code-coverage", 936 | "version": "9.2.29", 937 | "source": { 938 | "type": "git", 939 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 940 | "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" 941 | }, 942 | "dist": { 943 | "type": "zip", 944 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", 945 | "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", 946 | "shasum": "" 947 | }, 948 | "require": { 949 | "ext-dom": "*", 950 | "ext-libxml": "*", 951 | "ext-xmlwriter": "*", 952 | "nikic/php-parser": "^4.15", 953 | "php": ">=7.3", 954 | "phpunit/php-file-iterator": "^3.0.3", 955 | "phpunit/php-text-template": "^2.0.2", 956 | "sebastian/code-unit-reverse-lookup": "^2.0.2", 957 | "sebastian/complexity": "^2.0", 958 | "sebastian/environment": "^5.1.2", 959 | "sebastian/lines-of-code": "^1.0.3", 960 | "sebastian/version": "^3.0.1", 961 | "theseer/tokenizer": "^1.2.0" 962 | }, 963 | "require-dev": { 964 | "phpunit/phpunit": "^9.3" 965 | }, 966 | "suggest": { 967 | "ext-pcov": "PHP extension that provides line coverage", 968 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 969 | }, 970 | "type": "library", 971 | "extra": { 972 | "branch-alias": { 973 | "dev-master": "9.2-dev" 974 | } 975 | }, 976 | "autoload": { 977 | "classmap": [ 978 | "src/" 979 | ] 980 | }, 981 | "notification-url": "https://packagist.org/downloads/", 982 | "license": [ 983 | "BSD-3-Clause" 984 | ], 985 | "authors": [ 986 | { 987 | "name": "Sebastian Bergmann", 988 | "email": "sebastian@phpunit.de", 989 | "role": "lead" 990 | } 991 | ], 992 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 993 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 994 | "keywords": [ 995 | "coverage", 996 | "testing", 997 | "xunit" 998 | ], 999 | "funding": [ 1000 | { 1001 | "url": "https://github.com/sebastianbergmann", 1002 | "type": "github" 1003 | } 1004 | ], 1005 | "time": "2023-09-19T04:57:46+00:00" 1006 | }, 1007 | { 1008 | "name": "phpunit/php-file-iterator", 1009 | "version": "3.0.6", 1010 | "source": { 1011 | "type": "git", 1012 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 1013 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" 1014 | }, 1015 | "dist": { 1016 | "type": "zip", 1017 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 1018 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 1019 | "shasum": "" 1020 | }, 1021 | "require": { 1022 | "php": ">=7.3" 1023 | }, 1024 | "require-dev": { 1025 | "phpunit/phpunit": "^9.3" 1026 | }, 1027 | "type": "library", 1028 | "extra": { 1029 | "branch-alias": { 1030 | "dev-master": "3.0-dev" 1031 | } 1032 | }, 1033 | "autoload": { 1034 | "classmap": [ 1035 | "src/" 1036 | ] 1037 | }, 1038 | "notification-url": "https://packagist.org/downloads/", 1039 | "license": [ 1040 | "BSD-3-Clause" 1041 | ], 1042 | "authors": [ 1043 | { 1044 | "name": "Sebastian Bergmann", 1045 | "email": "sebastian@phpunit.de", 1046 | "role": "lead" 1047 | } 1048 | ], 1049 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1050 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1051 | "keywords": [ 1052 | "filesystem", 1053 | "iterator" 1054 | ], 1055 | "funding": [ 1056 | { 1057 | "url": "https://github.com/sebastianbergmann", 1058 | "type": "github" 1059 | } 1060 | ], 1061 | "time": "2021-12-02T12:48:52+00:00" 1062 | }, 1063 | { 1064 | "name": "phpunit/php-invoker", 1065 | "version": "3.1.1", 1066 | "source": { 1067 | "type": "git", 1068 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 1069 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" 1070 | }, 1071 | "dist": { 1072 | "type": "zip", 1073 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 1074 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 1075 | "shasum": "" 1076 | }, 1077 | "require": { 1078 | "php": ">=7.3" 1079 | }, 1080 | "require-dev": { 1081 | "ext-pcntl": "*", 1082 | "phpunit/phpunit": "^9.3" 1083 | }, 1084 | "suggest": { 1085 | "ext-pcntl": "*" 1086 | }, 1087 | "type": "library", 1088 | "extra": { 1089 | "branch-alias": { 1090 | "dev-master": "3.1-dev" 1091 | } 1092 | }, 1093 | "autoload": { 1094 | "classmap": [ 1095 | "src/" 1096 | ] 1097 | }, 1098 | "notification-url": "https://packagist.org/downloads/", 1099 | "license": [ 1100 | "BSD-3-Clause" 1101 | ], 1102 | "authors": [ 1103 | { 1104 | "name": "Sebastian Bergmann", 1105 | "email": "sebastian@phpunit.de", 1106 | "role": "lead" 1107 | } 1108 | ], 1109 | "description": "Invoke callables with a timeout", 1110 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 1111 | "keywords": [ 1112 | "process" 1113 | ], 1114 | "funding": [ 1115 | { 1116 | "url": "https://github.com/sebastianbergmann", 1117 | "type": "github" 1118 | } 1119 | ], 1120 | "time": "2020-09-28T05:58:55+00:00" 1121 | }, 1122 | { 1123 | "name": "phpunit/php-text-template", 1124 | "version": "2.0.4", 1125 | "source": { 1126 | "type": "git", 1127 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1128 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" 1129 | }, 1130 | "dist": { 1131 | "type": "zip", 1132 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 1133 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 1134 | "shasum": "" 1135 | }, 1136 | "require": { 1137 | "php": ">=7.3" 1138 | }, 1139 | "require-dev": { 1140 | "phpunit/phpunit": "^9.3" 1141 | }, 1142 | "type": "library", 1143 | "extra": { 1144 | "branch-alias": { 1145 | "dev-master": "2.0-dev" 1146 | } 1147 | }, 1148 | "autoload": { 1149 | "classmap": [ 1150 | "src/" 1151 | ] 1152 | }, 1153 | "notification-url": "https://packagist.org/downloads/", 1154 | "license": [ 1155 | "BSD-3-Clause" 1156 | ], 1157 | "authors": [ 1158 | { 1159 | "name": "Sebastian Bergmann", 1160 | "email": "sebastian@phpunit.de", 1161 | "role": "lead" 1162 | } 1163 | ], 1164 | "description": "Simple template engine.", 1165 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1166 | "keywords": [ 1167 | "template" 1168 | ], 1169 | "funding": [ 1170 | { 1171 | "url": "https://github.com/sebastianbergmann", 1172 | "type": "github" 1173 | } 1174 | ], 1175 | "time": "2020-10-26T05:33:50+00:00" 1176 | }, 1177 | { 1178 | "name": "phpunit/php-timer", 1179 | "version": "5.0.3", 1180 | "source": { 1181 | "type": "git", 1182 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1183 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" 1184 | }, 1185 | "dist": { 1186 | "type": "zip", 1187 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 1188 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 1189 | "shasum": "" 1190 | }, 1191 | "require": { 1192 | "php": ">=7.3" 1193 | }, 1194 | "require-dev": { 1195 | "phpunit/phpunit": "^9.3" 1196 | }, 1197 | "type": "library", 1198 | "extra": { 1199 | "branch-alias": { 1200 | "dev-master": "5.0-dev" 1201 | } 1202 | }, 1203 | "autoload": { 1204 | "classmap": [ 1205 | "src/" 1206 | ] 1207 | }, 1208 | "notification-url": "https://packagist.org/downloads/", 1209 | "license": [ 1210 | "BSD-3-Clause" 1211 | ], 1212 | "authors": [ 1213 | { 1214 | "name": "Sebastian Bergmann", 1215 | "email": "sebastian@phpunit.de", 1216 | "role": "lead" 1217 | } 1218 | ], 1219 | "description": "Utility class for timing", 1220 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1221 | "keywords": [ 1222 | "timer" 1223 | ], 1224 | "funding": [ 1225 | { 1226 | "url": "https://github.com/sebastianbergmann", 1227 | "type": "github" 1228 | } 1229 | ], 1230 | "time": "2020-10-26T13:16:10+00:00" 1231 | }, 1232 | { 1233 | "name": "phpunit/phpunit", 1234 | "version": "9.6.15", 1235 | "source": { 1236 | "type": "git", 1237 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1238 | "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" 1239 | }, 1240 | "dist": { 1241 | "type": "zip", 1242 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", 1243 | "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", 1244 | "shasum": "" 1245 | }, 1246 | "require": { 1247 | "doctrine/instantiator": "^1.3.1 || ^2", 1248 | "ext-dom": "*", 1249 | "ext-json": "*", 1250 | "ext-libxml": "*", 1251 | "ext-mbstring": "*", 1252 | "ext-xml": "*", 1253 | "ext-xmlwriter": "*", 1254 | "myclabs/deep-copy": "^1.10.1", 1255 | "phar-io/manifest": "^2.0.3", 1256 | "phar-io/version": "^3.0.2", 1257 | "php": ">=7.3", 1258 | "phpunit/php-code-coverage": "^9.2.28", 1259 | "phpunit/php-file-iterator": "^3.0.5", 1260 | "phpunit/php-invoker": "^3.1.1", 1261 | "phpunit/php-text-template": "^2.0.3", 1262 | "phpunit/php-timer": "^5.0.2", 1263 | "sebastian/cli-parser": "^1.0.1", 1264 | "sebastian/code-unit": "^1.0.6", 1265 | "sebastian/comparator": "^4.0.8", 1266 | "sebastian/diff": "^4.0.3", 1267 | "sebastian/environment": "^5.1.3", 1268 | "sebastian/exporter": "^4.0.5", 1269 | "sebastian/global-state": "^5.0.1", 1270 | "sebastian/object-enumerator": "^4.0.3", 1271 | "sebastian/resource-operations": "^3.0.3", 1272 | "sebastian/type": "^3.2", 1273 | "sebastian/version": "^3.0.2" 1274 | }, 1275 | "suggest": { 1276 | "ext-soap": "To be able to generate mocks based on WSDL files", 1277 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 1278 | }, 1279 | "bin": [ 1280 | "phpunit" 1281 | ], 1282 | "type": "library", 1283 | "extra": { 1284 | "branch-alias": { 1285 | "dev-master": "9.6-dev" 1286 | } 1287 | }, 1288 | "autoload": { 1289 | "files": [ 1290 | "src/Framework/Assert/Functions.php" 1291 | ], 1292 | "classmap": [ 1293 | "src/" 1294 | ] 1295 | }, 1296 | "notification-url": "https://packagist.org/downloads/", 1297 | "license": [ 1298 | "BSD-3-Clause" 1299 | ], 1300 | "authors": [ 1301 | { 1302 | "name": "Sebastian Bergmann", 1303 | "email": "sebastian@phpunit.de", 1304 | "role": "lead" 1305 | } 1306 | ], 1307 | "description": "The PHP Unit Testing framework.", 1308 | "homepage": "https://phpunit.de/", 1309 | "keywords": [ 1310 | "phpunit", 1311 | "testing", 1312 | "xunit" 1313 | ], 1314 | "funding": [ 1315 | { 1316 | "url": "https://phpunit.de/sponsors.html", 1317 | "type": "custom" 1318 | }, 1319 | { 1320 | "url": "https://github.com/sebastianbergmann", 1321 | "type": "github" 1322 | }, 1323 | { 1324 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 1325 | "type": "tidelift" 1326 | } 1327 | ], 1328 | "time": "2023-12-01T16:55:19+00:00" 1329 | }, 1330 | { 1331 | "name": "psr/container", 1332 | "version": "1.1.1", 1333 | "source": { 1334 | "type": "git", 1335 | "url": "https://github.com/php-fig/container.git", 1336 | "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" 1337 | }, 1338 | "dist": { 1339 | "type": "zip", 1340 | "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", 1341 | "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", 1342 | "shasum": "" 1343 | }, 1344 | "require": { 1345 | "php": ">=7.2.0" 1346 | }, 1347 | "type": "library", 1348 | "autoload": { 1349 | "psr-4": { 1350 | "Psr\\Container\\": "src/" 1351 | } 1352 | }, 1353 | "notification-url": "https://packagist.org/downloads/", 1354 | "license": [ 1355 | "MIT" 1356 | ], 1357 | "authors": [ 1358 | { 1359 | "name": "PHP-FIG", 1360 | "homepage": "https://www.php-fig.org/" 1361 | } 1362 | ], 1363 | "description": "Common Container Interface (PHP FIG PSR-11)", 1364 | "homepage": "https://github.com/php-fig/container", 1365 | "keywords": [ 1366 | "PSR-11", 1367 | "container", 1368 | "container-interface", 1369 | "container-interop", 1370 | "psr" 1371 | ], 1372 | "time": "2021-03-05T17:36:06+00:00" 1373 | }, 1374 | { 1375 | "name": "psr/log", 1376 | "version": "1.1.4", 1377 | "source": { 1378 | "type": "git", 1379 | "url": "https://github.com/php-fig/log.git", 1380 | "reference": "d49695b909c3b7628b6289db5479a1c204601f11" 1381 | }, 1382 | "dist": { 1383 | "type": "zip", 1384 | "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", 1385 | "reference": "d49695b909c3b7628b6289db5479a1c204601f11", 1386 | "shasum": "" 1387 | }, 1388 | "require": { 1389 | "php": ">=5.3.0" 1390 | }, 1391 | "type": "library", 1392 | "extra": { 1393 | "branch-alias": { 1394 | "dev-master": "1.1.x-dev" 1395 | } 1396 | }, 1397 | "autoload": { 1398 | "psr-4": { 1399 | "Psr\\Log\\": "Psr/Log/" 1400 | } 1401 | }, 1402 | "notification-url": "https://packagist.org/downloads/", 1403 | "license": [ 1404 | "MIT" 1405 | ], 1406 | "authors": [ 1407 | { 1408 | "name": "PHP-FIG", 1409 | "homepage": "https://www.php-fig.org/" 1410 | } 1411 | ], 1412 | "description": "Common interface for logging libraries", 1413 | "homepage": "https://github.com/php-fig/log", 1414 | "keywords": [ 1415 | "log", 1416 | "psr", 1417 | "psr-3" 1418 | ], 1419 | "time": "2021-05-03T11:20:27+00:00" 1420 | }, 1421 | { 1422 | "name": "sebastian/cli-parser", 1423 | "version": "1.0.1", 1424 | "source": { 1425 | "type": "git", 1426 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 1427 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" 1428 | }, 1429 | "dist": { 1430 | "type": "zip", 1431 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", 1432 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", 1433 | "shasum": "" 1434 | }, 1435 | "require": { 1436 | "php": ">=7.3" 1437 | }, 1438 | "require-dev": { 1439 | "phpunit/phpunit": "^9.3" 1440 | }, 1441 | "type": "library", 1442 | "extra": { 1443 | "branch-alias": { 1444 | "dev-master": "1.0-dev" 1445 | } 1446 | }, 1447 | "autoload": { 1448 | "classmap": [ 1449 | "src/" 1450 | ] 1451 | }, 1452 | "notification-url": "https://packagist.org/downloads/", 1453 | "license": [ 1454 | "BSD-3-Clause" 1455 | ], 1456 | "authors": [ 1457 | { 1458 | "name": "Sebastian Bergmann", 1459 | "email": "sebastian@phpunit.de", 1460 | "role": "lead" 1461 | } 1462 | ], 1463 | "description": "Library for parsing CLI options", 1464 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 1465 | "funding": [ 1466 | { 1467 | "url": "https://github.com/sebastianbergmann", 1468 | "type": "github" 1469 | } 1470 | ], 1471 | "time": "2020-09-28T06:08:49+00:00" 1472 | }, 1473 | { 1474 | "name": "sebastian/code-unit", 1475 | "version": "1.0.8", 1476 | "source": { 1477 | "type": "git", 1478 | "url": "https://github.com/sebastianbergmann/code-unit.git", 1479 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" 1480 | }, 1481 | "dist": { 1482 | "type": "zip", 1483 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", 1484 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", 1485 | "shasum": "" 1486 | }, 1487 | "require": { 1488 | "php": ">=7.3" 1489 | }, 1490 | "require-dev": { 1491 | "phpunit/phpunit": "^9.3" 1492 | }, 1493 | "type": "library", 1494 | "extra": { 1495 | "branch-alias": { 1496 | "dev-master": "1.0-dev" 1497 | } 1498 | }, 1499 | "autoload": { 1500 | "classmap": [ 1501 | "src/" 1502 | ] 1503 | }, 1504 | "notification-url": "https://packagist.org/downloads/", 1505 | "license": [ 1506 | "BSD-3-Clause" 1507 | ], 1508 | "authors": [ 1509 | { 1510 | "name": "Sebastian Bergmann", 1511 | "email": "sebastian@phpunit.de", 1512 | "role": "lead" 1513 | } 1514 | ], 1515 | "description": "Collection of value objects that represent the PHP code units", 1516 | "homepage": "https://github.com/sebastianbergmann/code-unit", 1517 | "funding": [ 1518 | { 1519 | "url": "https://github.com/sebastianbergmann", 1520 | "type": "github" 1521 | } 1522 | ], 1523 | "time": "2020-10-26T13:08:54+00:00" 1524 | }, 1525 | { 1526 | "name": "sebastian/code-unit-reverse-lookup", 1527 | "version": "2.0.3", 1528 | "source": { 1529 | "type": "git", 1530 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1531 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" 1532 | }, 1533 | "dist": { 1534 | "type": "zip", 1535 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1536 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1537 | "shasum": "" 1538 | }, 1539 | "require": { 1540 | "php": ">=7.3" 1541 | }, 1542 | "require-dev": { 1543 | "phpunit/phpunit": "^9.3" 1544 | }, 1545 | "type": "library", 1546 | "extra": { 1547 | "branch-alias": { 1548 | "dev-master": "2.0-dev" 1549 | } 1550 | }, 1551 | "autoload": { 1552 | "classmap": [ 1553 | "src/" 1554 | ] 1555 | }, 1556 | "notification-url": "https://packagist.org/downloads/", 1557 | "license": [ 1558 | "BSD-3-Clause" 1559 | ], 1560 | "authors": [ 1561 | { 1562 | "name": "Sebastian Bergmann", 1563 | "email": "sebastian@phpunit.de" 1564 | } 1565 | ], 1566 | "description": "Looks up which function or method a line of code belongs to", 1567 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1568 | "funding": [ 1569 | { 1570 | "url": "https://github.com/sebastianbergmann", 1571 | "type": "github" 1572 | } 1573 | ], 1574 | "time": "2020-09-28T05:30:19+00:00" 1575 | }, 1576 | { 1577 | "name": "sebastian/comparator", 1578 | "version": "4.0.8", 1579 | "source": { 1580 | "type": "git", 1581 | "url": "https://github.com/sebastianbergmann/comparator.git", 1582 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a" 1583 | }, 1584 | "dist": { 1585 | "type": "zip", 1586 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", 1587 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a", 1588 | "shasum": "" 1589 | }, 1590 | "require": { 1591 | "php": ">=7.3", 1592 | "sebastian/diff": "^4.0", 1593 | "sebastian/exporter": "^4.0" 1594 | }, 1595 | "require-dev": { 1596 | "phpunit/phpunit": "^9.3" 1597 | }, 1598 | "type": "library", 1599 | "extra": { 1600 | "branch-alias": { 1601 | "dev-master": "4.0-dev" 1602 | } 1603 | }, 1604 | "autoload": { 1605 | "classmap": [ 1606 | "src/" 1607 | ] 1608 | }, 1609 | "notification-url": "https://packagist.org/downloads/", 1610 | "license": [ 1611 | "BSD-3-Clause" 1612 | ], 1613 | "authors": [ 1614 | { 1615 | "name": "Sebastian Bergmann", 1616 | "email": "sebastian@phpunit.de" 1617 | }, 1618 | { 1619 | "name": "Jeff Welch", 1620 | "email": "whatthejeff@gmail.com" 1621 | }, 1622 | { 1623 | "name": "Volker Dusch", 1624 | "email": "github@wallbash.com" 1625 | }, 1626 | { 1627 | "name": "Bernhard Schussek", 1628 | "email": "bschussek@2bepublished.at" 1629 | } 1630 | ], 1631 | "description": "Provides the functionality to compare PHP values for equality", 1632 | "homepage": "https://github.com/sebastianbergmann/comparator", 1633 | "keywords": [ 1634 | "comparator", 1635 | "compare", 1636 | "equality" 1637 | ], 1638 | "funding": [ 1639 | { 1640 | "url": "https://github.com/sebastianbergmann", 1641 | "type": "github" 1642 | } 1643 | ], 1644 | "time": "2022-09-14T12:41:17+00:00" 1645 | }, 1646 | { 1647 | "name": "sebastian/complexity", 1648 | "version": "2.0.2", 1649 | "source": { 1650 | "type": "git", 1651 | "url": "https://github.com/sebastianbergmann/complexity.git", 1652 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" 1653 | }, 1654 | "dist": { 1655 | "type": "zip", 1656 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", 1657 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", 1658 | "shasum": "" 1659 | }, 1660 | "require": { 1661 | "nikic/php-parser": "^4.7", 1662 | "php": ">=7.3" 1663 | }, 1664 | "require-dev": { 1665 | "phpunit/phpunit": "^9.3" 1666 | }, 1667 | "type": "library", 1668 | "extra": { 1669 | "branch-alias": { 1670 | "dev-master": "2.0-dev" 1671 | } 1672 | }, 1673 | "autoload": { 1674 | "classmap": [ 1675 | "src/" 1676 | ] 1677 | }, 1678 | "notification-url": "https://packagist.org/downloads/", 1679 | "license": [ 1680 | "BSD-3-Clause" 1681 | ], 1682 | "authors": [ 1683 | { 1684 | "name": "Sebastian Bergmann", 1685 | "email": "sebastian@phpunit.de", 1686 | "role": "lead" 1687 | } 1688 | ], 1689 | "description": "Library for calculating the complexity of PHP code units", 1690 | "homepage": "https://github.com/sebastianbergmann/complexity", 1691 | "funding": [ 1692 | { 1693 | "url": "https://github.com/sebastianbergmann", 1694 | "type": "github" 1695 | } 1696 | ], 1697 | "time": "2020-10-26T15:52:27+00:00" 1698 | }, 1699 | { 1700 | "name": "sebastian/diff", 1701 | "version": "4.0.5", 1702 | "source": { 1703 | "type": "git", 1704 | "url": "https://github.com/sebastianbergmann/diff.git", 1705 | "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" 1706 | }, 1707 | "dist": { 1708 | "type": "zip", 1709 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", 1710 | "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", 1711 | "shasum": "" 1712 | }, 1713 | "require": { 1714 | "php": ">=7.3" 1715 | }, 1716 | "require-dev": { 1717 | "phpunit/phpunit": "^9.3", 1718 | "symfony/process": "^4.2 || ^5" 1719 | }, 1720 | "type": "library", 1721 | "extra": { 1722 | "branch-alias": { 1723 | "dev-master": "4.0-dev" 1724 | } 1725 | }, 1726 | "autoload": { 1727 | "classmap": [ 1728 | "src/" 1729 | ] 1730 | }, 1731 | "notification-url": "https://packagist.org/downloads/", 1732 | "license": [ 1733 | "BSD-3-Clause" 1734 | ], 1735 | "authors": [ 1736 | { 1737 | "name": "Sebastian Bergmann", 1738 | "email": "sebastian@phpunit.de" 1739 | }, 1740 | { 1741 | "name": "Kore Nordmann", 1742 | "email": "mail@kore-nordmann.de" 1743 | } 1744 | ], 1745 | "description": "Diff implementation", 1746 | "homepage": "https://github.com/sebastianbergmann/diff", 1747 | "keywords": [ 1748 | "diff", 1749 | "udiff", 1750 | "unidiff", 1751 | "unified diff" 1752 | ], 1753 | "funding": [ 1754 | { 1755 | "url": "https://github.com/sebastianbergmann", 1756 | "type": "github" 1757 | } 1758 | ], 1759 | "time": "2023-05-07T05:35:17+00:00" 1760 | }, 1761 | { 1762 | "name": "sebastian/environment", 1763 | "version": "5.1.5", 1764 | "source": { 1765 | "type": "git", 1766 | "url": "https://github.com/sebastianbergmann/environment.git", 1767 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" 1768 | }, 1769 | "dist": { 1770 | "type": "zip", 1771 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1772 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1773 | "shasum": "" 1774 | }, 1775 | "require": { 1776 | "php": ">=7.3" 1777 | }, 1778 | "require-dev": { 1779 | "phpunit/phpunit": "^9.3" 1780 | }, 1781 | "suggest": { 1782 | "ext-posix": "*" 1783 | }, 1784 | "type": "library", 1785 | "extra": { 1786 | "branch-alias": { 1787 | "dev-master": "5.1-dev" 1788 | } 1789 | }, 1790 | "autoload": { 1791 | "classmap": [ 1792 | "src/" 1793 | ] 1794 | }, 1795 | "notification-url": "https://packagist.org/downloads/", 1796 | "license": [ 1797 | "BSD-3-Clause" 1798 | ], 1799 | "authors": [ 1800 | { 1801 | "name": "Sebastian Bergmann", 1802 | "email": "sebastian@phpunit.de" 1803 | } 1804 | ], 1805 | "description": "Provides functionality to handle HHVM/PHP environments", 1806 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1807 | "keywords": [ 1808 | "Xdebug", 1809 | "environment", 1810 | "hhvm" 1811 | ], 1812 | "funding": [ 1813 | { 1814 | "url": "https://github.com/sebastianbergmann", 1815 | "type": "github" 1816 | } 1817 | ], 1818 | "time": "2023-02-03T06:03:51+00:00" 1819 | }, 1820 | { 1821 | "name": "sebastian/exporter", 1822 | "version": "4.0.5", 1823 | "source": { 1824 | "type": "git", 1825 | "url": "https://github.com/sebastianbergmann/exporter.git", 1826 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" 1827 | }, 1828 | "dist": { 1829 | "type": "zip", 1830 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", 1831 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", 1832 | "shasum": "" 1833 | }, 1834 | "require": { 1835 | "php": ">=7.3", 1836 | "sebastian/recursion-context": "^4.0" 1837 | }, 1838 | "require-dev": { 1839 | "ext-mbstring": "*", 1840 | "phpunit/phpunit": "^9.3" 1841 | }, 1842 | "type": "library", 1843 | "extra": { 1844 | "branch-alias": { 1845 | "dev-master": "4.0-dev" 1846 | } 1847 | }, 1848 | "autoload": { 1849 | "classmap": [ 1850 | "src/" 1851 | ] 1852 | }, 1853 | "notification-url": "https://packagist.org/downloads/", 1854 | "license": [ 1855 | "BSD-3-Clause" 1856 | ], 1857 | "authors": [ 1858 | { 1859 | "name": "Sebastian Bergmann", 1860 | "email": "sebastian@phpunit.de" 1861 | }, 1862 | { 1863 | "name": "Jeff Welch", 1864 | "email": "whatthejeff@gmail.com" 1865 | }, 1866 | { 1867 | "name": "Volker Dusch", 1868 | "email": "github@wallbash.com" 1869 | }, 1870 | { 1871 | "name": "Adam Harvey", 1872 | "email": "aharvey@php.net" 1873 | }, 1874 | { 1875 | "name": "Bernhard Schussek", 1876 | "email": "bschussek@gmail.com" 1877 | } 1878 | ], 1879 | "description": "Provides the functionality to export PHP variables for visualization", 1880 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 1881 | "keywords": [ 1882 | "export", 1883 | "exporter" 1884 | ], 1885 | "funding": [ 1886 | { 1887 | "url": "https://github.com/sebastianbergmann", 1888 | "type": "github" 1889 | } 1890 | ], 1891 | "time": "2022-09-14T06:03:37+00:00" 1892 | }, 1893 | { 1894 | "name": "sebastian/global-state", 1895 | "version": "5.0.6", 1896 | "source": { 1897 | "type": "git", 1898 | "url": "https://github.com/sebastianbergmann/global-state.git", 1899 | "reference": "bde739e7565280bda77be70044ac1047bc007e34" 1900 | }, 1901 | "dist": { 1902 | "type": "zip", 1903 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", 1904 | "reference": "bde739e7565280bda77be70044ac1047bc007e34", 1905 | "shasum": "" 1906 | }, 1907 | "require": { 1908 | "php": ">=7.3", 1909 | "sebastian/object-reflector": "^2.0", 1910 | "sebastian/recursion-context": "^4.0" 1911 | }, 1912 | "require-dev": { 1913 | "ext-dom": "*", 1914 | "phpunit/phpunit": "^9.3" 1915 | }, 1916 | "suggest": { 1917 | "ext-uopz": "*" 1918 | }, 1919 | "type": "library", 1920 | "extra": { 1921 | "branch-alias": { 1922 | "dev-master": "5.0-dev" 1923 | } 1924 | }, 1925 | "autoload": { 1926 | "classmap": [ 1927 | "src/" 1928 | ] 1929 | }, 1930 | "notification-url": "https://packagist.org/downloads/", 1931 | "license": [ 1932 | "BSD-3-Clause" 1933 | ], 1934 | "authors": [ 1935 | { 1936 | "name": "Sebastian Bergmann", 1937 | "email": "sebastian@phpunit.de" 1938 | } 1939 | ], 1940 | "description": "Snapshotting of global state", 1941 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1942 | "keywords": [ 1943 | "global state" 1944 | ], 1945 | "funding": [ 1946 | { 1947 | "url": "https://github.com/sebastianbergmann", 1948 | "type": "github" 1949 | } 1950 | ], 1951 | "time": "2023-08-02T09:26:13+00:00" 1952 | }, 1953 | { 1954 | "name": "sebastian/lines-of-code", 1955 | "version": "1.0.3", 1956 | "source": { 1957 | "type": "git", 1958 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 1959 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" 1960 | }, 1961 | "dist": { 1962 | "type": "zip", 1963 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", 1964 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", 1965 | "shasum": "" 1966 | }, 1967 | "require": { 1968 | "nikic/php-parser": "^4.6", 1969 | "php": ">=7.3" 1970 | }, 1971 | "require-dev": { 1972 | "phpunit/phpunit": "^9.3" 1973 | }, 1974 | "type": "library", 1975 | "extra": { 1976 | "branch-alias": { 1977 | "dev-master": "1.0-dev" 1978 | } 1979 | }, 1980 | "autoload": { 1981 | "classmap": [ 1982 | "src/" 1983 | ] 1984 | }, 1985 | "notification-url": "https://packagist.org/downloads/", 1986 | "license": [ 1987 | "BSD-3-Clause" 1988 | ], 1989 | "authors": [ 1990 | { 1991 | "name": "Sebastian Bergmann", 1992 | "email": "sebastian@phpunit.de", 1993 | "role": "lead" 1994 | } 1995 | ], 1996 | "description": "Library for counting the lines of code in PHP source code", 1997 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 1998 | "funding": [ 1999 | { 2000 | "url": "https://github.com/sebastianbergmann", 2001 | "type": "github" 2002 | } 2003 | ], 2004 | "time": "2020-11-28T06:42:11+00:00" 2005 | }, 2006 | { 2007 | "name": "sebastian/object-enumerator", 2008 | "version": "4.0.4", 2009 | "source": { 2010 | "type": "git", 2011 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 2012 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" 2013 | }, 2014 | "dist": { 2015 | "type": "zip", 2016 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", 2017 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", 2018 | "shasum": "" 2019 | }, 2020 | "require": { 2021 | "php": ">=7.3", 2022 | "sebastian/object-reflector": "^2.0", 2023 | "sebastian/recursion-context": "^4.0" 2024 | }, 2025 | "require-dev": { 2026 | "phpunit/phpunit": "^9.3" 2027 | }, 2028 | "type": "library", 2029 | "extra": { 2030 | "branch-alias": { 2031 | "dev-master": "4.0-dev" 2032 | } 2033 | }, 2034 | "autoload": { 2035 | "classmap": [ 2036 | "src/" 2037 | ] 2038 | }, 2039 | "notification-url": "https://packagist.org/downloads/", 2040 | "license": [ 2041 | "BSD-3-Clause" 2042 | ], 2043 | "authors": [ 2044 | { 2045 | "name": "Sebastian Bergmann", 2046 | "email": "sebastian@phpunit.de" 2047 | } 2048 | ], 2049 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 2050 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 2051 | "funding": [ 2052 | { 2053 | "url": "https://github.com/sebastianbergmann", 2054 | "type": "github" 2055 | } 2056 | ], 2057 | "time": "2020-10-26T13:12:34+00:00" 2058 | }, 2059 | { 2060 | "name": "sebastian/object-reflector", 2061 | "version": "2.0.4", 2062 | "source": { 2063 | "type": "git", 2064 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 2065 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" 2066 | }, 2067 | "dist": { 2068 | "type": "zip", 2069 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 2070 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 2071 | "shasum": "" 2072 | }, 2073 | "require": { 2074 | "php": ">=7.3" 2075 | }, 2076 | "require-dev": { 2077 | "phpunit/phpunit": "^9.3" 2078 | }, 2079 | "type": "library", 2080 | "extra": { 2081 | "branch-alias": { 2082 | "dev-master": "2.0-dev" 2083 | } 2084 | }, 2085 | "autoload": { 2086 | "classmap": [ 2087 | "src/" 2088 | ] 2089 | }, 2090 | "notification-url": "https://packagist.org/downloads/", 2091 | "license": [ 2092 | "BSD-3-Clause" 2093 | ], 2094 | "authors": [ 2095 | { 2096 | "name": "Sebastian Bergmann", 2097 | "email": "sebastian@phpunit.de" 2098 | } 2099 | ], 2100 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 2101 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 2102 | "funding": [ 2103 | { 2104 | "url": "https://github.com/sebastianbergmann", 2105 | "type": "github" 2106 | } 2107 | ], 2108 | "time": "2020-10-26T13:14:26+00:00" 2109 | }, 2110 | { 2111 | "name": "sebastian/recursion-context", 2112 | "version": "4.0.5", 2113 | "source": { 2114 | "type": "git", 2115 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 2116 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" 2117 | }, 2118 | "dist": { 2119 | "type": "zip", 2120 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 2121 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 2122 | "shasum": "" 2123 | }, 2124 | "require": { 2125 | "php": ">=7.3" 2126 | }, 2127 | "require-dev": { 2128 | "phpunit/phpunit": "^9.3" 2129 | }, 2130 | "type": "library", 2131 | "extra": { 2132 | "branch-alias": { 2133 | "dev-master": "4.0-dev" 2134 | } 2135 | }, 2136 | "autoload": { 2137 | "classmap": [ 2138 | "src/" 2139 | ] 2140 | }, 2141 | "notification-url": "https://packagist.org/downloads/", 2142 | "license": [ 2143 | "BSD-3-Clause" 2144 | ], 2145 | "authors": [ 2146 | { 2147 | "name": "Sebastian Bergmann", 2148 | "email": "sebastian@phpunit.de" 2149 | }, 2150 | { 2151 | "name": "Jeff Welch", 2152 | "email": "whatthejeff@gmail.com" 2153 | }, 2154 | { 2155 | "name": "Adam Harvey", 2156 | "email": "aharvey@php.net" 2157 | } 2158 | ], 2159 | "description": "Provides functionality to recursively process PHP variables", 2160 | "homepage": "https://github.com/sebastianbergmann/recursion-context", 2161 | "funding": [ 2162 | { 2163 | "url": "https://github.com/sebastianbergmann", 2164 | "type": "github" 2165 | } 2166 | ], 2167 | "time": "2023-02-03T06:07:39+00:00" 2168 | }, 2169 | { 2170 | "name": "sebastian/resource-operations", 2171 | "version": "3.0.3", 2172 | "source": { 2173 | "type": "git", 2174 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 2175 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" 2176 | }, 2177 | "dist": { 2178 | "type": "zip", 2179 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 2180 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 2181 | "shasum": "" 2182 | }, 2183 | "require": { 2184 | "php": ">=7.3" 2185 | }, 2186 | "require-dev": { 2187 | "phpunit/phpunit": "^9.0" 2188 | }, 2189 | "type": "library", 2190 | "extra": { 2191 | "branch-alias": { 2192 | "dev-master": "3.0-dev" 2193 | } 2194 | }, 2195 | "autoload": { 2196 | "classmap": [ 2197 | "src/" 2198 | ] 2199 | }, 2200 | "notification-url": "https://packagist.org/downloads/", 2201 | "license": [ 2202 | "BSD-3-Clause" 2203 | ], 2204 | "authors": [ 2205 | { 2206 | "name": "Sebastian Bergmann", 2207 | "email": "sebastian@phpunit.de" 2208 | } 2209 | ], 2210 | "description": "Provides a list of PHP built-in functions that operate on resources", 2211 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 2212 | "funding": [ 2213 | { 2214 | "url": "https://github.com/sebastianbergmann", 2215 | "type": "github" 2216 | } 2217 | ], 2218 | "time": "2020-09-28T06:45:17+00:00" 2219 | }, 2220 | { 2221 | "name": "sebastian/type", 2222 | "version": "3.2.1", 2223 | "source": { 2224 | "type": "git", 2225 | "url": "https://github.com/sebastianbergmann/type.git", 2226 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" 2227 | }, 2228 | "dist": { 2229 | "type": "zip", 2230 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 2231 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 2232 | "shasum": "" 2233 | }, 2234 | "require": { 2235 | "php": ">=7.3" 2236 | }, 2237 | "require-dev": { 2238 | "phpunit/phpunit": "^9.5" 2239 | }, 2240 | "type": "library", 2241 | "extra": { 2242 | "branch-alias": { 2243 | "dev-master": "3.2-dev" 2244 | } 2245 | }, 2246 | "autoload": { 2247 | "classmap": [ 2248 | "src/" 2249 | ] 2250 | }, 2251 | "notification-url": "https://packagist.org/downloads/", 2252 | "license": [ 2253 | "BSD-3-Clause" 2254 | ], 2255 | "authors": [ 2256 | { 2257 | "name": "Sebastian Bergmann", 2258 | "email": "sebastian@phpunit.de", 2259 | "role": "lead" 2260 | } 2261 | ], 2262 | "description": "Collection of value objects that represent the types of the PHP type system", 2263 | "homepage": "https://github.com/sebastianbergmann/type", 2264 | "funding": [ 2265 | { 2266 | "url": "https://github.com/sebastianbergmann", 2267 | "type": "github" 2268 | } 2269 | ], 2270 | "time": "2023-02-03T06:13:03+00:00" 2271 | }, 2272 | { 2273 | "name": "sebastian/version", 2274 | "version": "3.0.2", 2275 | "source": { 2276 | "type": "git", 2277 | "url": "https://github.com/sebastianbergmann/version.git", 2278 | "reference": "c6c1022351a901512170118436c764e473f6de8c" 2279 | }, 2280 | "dist": { 2281 | "type": "zip", 2282 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", 2283 | "reference": "c6c1022351a901512170118436c764e473f6de8c", 2284 | "shasum": "" 2285 | }, 2286 | "require": { 2287 | "php": ">=7.3" 2288 | }, 2289 | "type": "library", 2290 | "extra": { 2291 | "branch-alias": { 2292 | "dev-master": "3.0-dev" 2293 | } 2294 | }, 2295 | "autoload": { 2296 | "classmap": [ 2297 | "src/" 2298 | ] 2299 | }, 2300 | "notification-url": "https://packagist.org/downloads/", 2301 | "license": [ 2302 | "BSD-3-Clause" 2303 | ], 2304 | "authors": [ 2305 | { 2306 | "name": "Sebastian Bergmann", 2307 | "email": "sebastian@phpunit.de", 2308 | "role": "lead" 2309 | } 2310 | ], 2311 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 2312 | "homepage": "https://github.com/sebastianbergmann/version", 2313 | "funding": [ 2314 | { 2315 | "url": "https://github.com/sebastianbergmann", 2316 | "type": "github" 2317 | } 2318 | ], 2319 | "time": "2020-09-28T06:39:44+00:00" 2320 | }, 2321 | { 2322 | "name": "symfony/config", 2323 | "version": "v5.4.31", 2324 | "source": { 2325 | "type": "git", 2326 | "url": "https://github.com/symfony/config.git", 2327 | "reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9" 2328 | }, 2329 | "dist": { 2330 | "type": "zip", 2331 | "url": "https://api.github.com/repos/symfony/config/zipball/dd5ea39de228813aba0c23c3a4153da2a4cf3cd9", 2332 | "reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9", 2333 | "shasum": "" 2334 | }, 2335 | "require": { 2336 | "php": ">=7.2.5", 2337 | "symfony/deprecation-contracts": "^2.1|^3", 2338 | "symfony/filesystem": "^4.4|^5.0|^6.0", 2339 | "symfony/polyfill-ctype": "~1.8", 2340 | "symfony/polyfill-php80": "^1.16", 2341 | "symfony/polyfill-php81": "^1.22" 2342 | }, 2343 | "conflict": { 2344 | "symfony/finder": "<4.4" 2345 | }, 2346 | "require-dev": { 2347 | "symfony/event-dispatcher": "^4.4|^5.0|^6.0", 2348 | "symfony/finder": "^4.4|^5.0|^6.0", 2349 | "symfony/messenger": "^4.4|^5.0|^6.0", 2350 | "symfony/service-contracts": "^1.1|^2|^3", 2351 | "symfony/yaml": "^4.4|^5.0|^6.0" 2352 | }, 2353 | "suggest": { 2354 | "symfony/yaml": "To use the yaml reference dumper" 2355 | }, 2356 | "type": "library", 2357 | "autoload": { 2358 | "psr-4": { 2359 | "Symfony\\Component\\Config\\": "" 2360 | }, 2361 | "exclude-from-classmap": [ 2362 | "/Tests/" 2363 | ] 2364 | }, 2365 | "notification-url": "https://packagist.org/downloads/", 2366 | "license": [ 2367 | "MIT" 2368 | ], 2369 | "authors": [ 2370 | { 2371 | "name": "Fabien Potencier", 2372 | "email": "fabien@symfony.com" 2373 | }, 2374 | { 2375 | "name": "Symfony Community", 2376 | "homepage": "https://symfony.com/contributors" 2377 | } 2378 | ], 2379 | "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", 2380 | "homepage": "https://symfony.com", 2381 | "funding": [ 2382 | { 2383 | "url": "https://symfony.com/sponsor", 2384 | "type": "custom" 2385 | }, 2386 | { 2387 | "url": "https://github.com/fabpot", 2388 | "type": "github" 2389 | }, 2390 | { 2391 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2392 | "type": "tidelift" 2393 | } 2394 | ], 2395 | "time": "2023-11-09T08:22:43+00:00" 2396 | }, 2397 | { 2398 | "name": "symfony/console", 2399 | "version": "v5.4.31", 2400 | "source": { 2401 | "type": "git", 2402 | "url": "https://github.com/symfony/console.git", 2403 | "reference": "11ac5f154e0e5c4c77af83ad11ead9165280b92a" 2404 | }, 2405 | "dist": { 2406 | "type": "zip", 2407 | "url": "https://api.github.com/repos/symfony/console/zipball/11ac5f154e0e5c4c77af83ad11ead9165280b92a", 2408 | "reference": "11ac5f154e0e5c4c77af83ad11ead9165280b92a", 2409 | "shasum": "" 2410 | }, 2411 | "require": { 2412 | "php": ">=7.2.5", 2413 | "symfony/deprecation-contracts": "^2.1|^3", 2414 | "symfony/polyfill-mbstring": "~1.0", 2415 | "symfony/polyfill-php73": "^1.9", 2416 | "symfony/polyfill-php80": "^1.16", 2417 | "symfony/service-contracts": "^1.1|^2|^3", 2418 | "symfony/string": "^5.1|^6.0" 2419 | }, 2420 | "conflict": { 2421 | "psr/log": ">=3", 2422 | "symfony/dependency-injection": "<4.4", 2423 | "symfony/dotenv": "<5.1", 2424 | "symfony/event-dispatcher": "<4.4", 2425 | "symfony/lock": "<4.4", 2426 | "symfony/process": "<4.4" 2427 | }, 2428 | "provide": { 2429 | "psr/log-implementation": "1.0|2.0" 2430 | }, 2431 | "require-dev": { 2432 | "psr/log": "^1|^2", 2433 | "symfony/config": "^4.4|^5.0|^6.0", 2434 | "symfony/dependency-injection": "^4.4|^5.0|^6.0", 2435 | "symfony/event-dispatcher": "^4.4|^5.0|^6.0", 2436 | "symfony/lock": "^4.4|^5.0|^6.0", 2437 | "symfony/process": "^4.4|^5.0|^6.0", 2438 | "symfony/var-dumper": "^4.4|^5.0|^6.0" 2439 | }, 2440 | "suggest": { 2441 | "psr/log": "For using the console logger", 2442 | "symfony/event-dispatcher": "", 2443 | "symfony/lock": "", 2444 | "symfony/process": "" 2445 | }, 2446 | "type": "library", 2447 | "autoload": { 2448 | "psr-4": { 2449 | "Symfony\\Component\\Console\\": "" 2450 | }, 2451 | "exclude-from-classmap": [ 2452 | "/Tests/" 2453 | ] 2454 | }, 2455 | "notification-url": "https://packagist.org/downloads/", 2456 | "license": [ 2457 | "MIT" 2458 | ], 2459 | "authors": [ 2460 | { 2461 | "name": "Fabien Potencier", 2462 | "email": "fabien@symfony.com" 2463 | }, 2464 | { 2465 | "name": "Symfony Community", 2466 | "homepage": "https://symfony.com/contributors" 2467 | } 2468 | ], 2469 | "description": "Eases the creation of beautiful and testable command line interfaces", 2470 | "homepage": "https://symfony.com", 2471 | "keywords": [ 2472 | "cli", 2473 | "command-line", 2474 | "console", 2475 | "terminal" 2476 | ], 2477 | "funding": [ 2478 | { 2479 | "url": "https://symfony.com/sponsor", 2480 | "type": "custom" 2481 | }, 2482 | { 2483 | "url": "https://github.com/fabpot", 2484 | "type": "github" 2485 | }, 2486 | { 2487 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2488 | "type": "tidelift" 2489 | } 2490 | ], 2491 | "time": "2023-10-31T07:58:33+00:00" 2492 | }, 2493 | { 2494 | "name": "symfony/filesystem", 2495 | "version": "v5.4.25", 2496 | "source": { 2497 | "type": "git", 2498 | "url": "https://github.com/symfony/filesystem.git", 2499 | "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364" 2500 | }, 2501 | "dist": { 2502 | "type": "zip", 2503 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", 2504 | "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", 2505 | "shasum": "" 2506 | }, 2507 | "require": { 2508 | "php": ">=7.2.5", 2509 | "symfony/polyfill-ctype": "~1.8", 2510 | "symfony/polyfill-mbstring": "~1.8", 2511 | "symfony/polyfill-php80": "^1.16" 2512 | }, 2513 | "type": "library", 2514 | "autoload": { 2515 | "psr-4": { 2516 | "Symfony\\Component\\Filesystem\\": "" 2517 | }, 2518 | "exclude-from-classmap": [ 2519 | "/Tests/" 2520 | ] 2521 | }, 2522 | "notification-url": "https://packagist.org/downloads/", 2523 | "license": [ 2524 | "MIT" 2525 | ], 2526 | "authors": [ 2527 | { 2528 | "name": "Fabien Potencier", 2529 | "email": "fabien@symfony.com" 2530 | }, 2531 | { 2532 | "name": "Symfony Community", 2533 | "homepage": "https://symfony.com/contributors" 2534 | } 2535 | ], 2536 | "description": "Provides basic utilities for the filesystem", 2537 | "homepage": "https://symfony.com", 2538 | "funding": [ 2539 | { 2540 | "url": "https://symfony.com/sponsor", 2541 | "type": "custom" 2542 | }, 2543 | { 2544 | "url": "https://github.com/fabpot", 2545 | "type": "github" 2546 | }, 2547 | { 2548 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2549 | "type": "tidelift" 2550 | } 2551 | ], 2552 | "time": "2023-05-31T13:04:02+00:00" 2553 | }, 2554 | { 2555 | "name": "symfony/polyfill-ctype", 2556 | "version": "v1.28.0", 2557 | "source": { 2558 | "type": "git", 2559 | "url": "https://github.com/symfony/polyfill-ctype.git", 2560 | "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" 2561 | }, 2562 | "dist": { 2563 | "type": "zip", 2564 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", 2565 | "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", 2566 | "shasum": "" 2567 | }, 2568 | "require": { 2569 | "php": ">=7.1" 2570 | }, 2571 | "provide": { 2572 | "ext-ctype": "*" 2573 | }, 2574 | "suggest": { 2575 | "ext-ctype": "For best performance" 2576 | }, 2577 | "type": "library", 2578 | "extra": { 2579 | "branch-alias": { 2580 | "dev-main": "1.28-dev" 2581 | }, 2582 | "thanks": { 2583 | "name": "symfony/polyfill", 2584 | "url": "https://github.com/symfony/polyfill" 2585 | } 2586 | }, 2587 | "autoload": { 2588 | "files": [ 2589 | "bootstrap.php" 2590 | ], 2591 | "psr-4": { 2592 | "Symfony\\Polyfill\\Ctype\\": "" 2593 | } 2594 | }, 2595 | "notification-url": "https://packagist.org/downloads/", 2596 | "license": [ 2597 | "MIT" 2598 | ], 2599 | "authors": [ 2600 | { 2601 | "name": "Gert de Pagter", 2602 | "email": "BackEndTea@gmail.com" 2603 | }, 2604 | { 2605 | "name": "Symfony Community", 2606 | "homepage": "https://symfony.com/contributors" 2607 | } 2608 | ], 2609 | "description": "Symfony polyfill for ctype functions", 2610 | "homepage": "https://symfony.com", 2611 | "keywords": [ 2612 | "compatibility", 2613 | "ctype", 2614 | "polyfill", 2615 | "portable" 2616 | ], 2617 | "funding": [ 2618 | { 2619 | "url": "https://symfony.com/sponsor", 2620 | "type": "custom" 2621 | }, 2622 | { 2623 | "url": "https://github.com/fabpot", 2624 | "type": "github" 2625 | }, 2626 | { 2627 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2628 | "type": "tidelift" 2629 | } 2630 | ], 2631 | "time": "2023-01-26T09:26:14+00:00" 2632 | }, 2633 | { 2634 | "name": "symfony/polyfill-intl-grapheme", 2635 | "version": "v1.28.0", 2636 | "source": { 2637 | "type": "git", 2638 | "url": "https://github.com/symfony/polyfill-intl-grapheme.git", 2639 | "reference": "875e90aeea2777b6f135677f618529449334a612" 2640 | }, 2641 | "dist": { 2642 | "type": "zip", 2643 | "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", 2644 | "reference": "875e90aeea2777b6f135677f618529449334a612", 2645 | "shasum": "" 2646 | }, 2647 | "require": { 2648 | "php": ">=7.1" 2649 | }, 2650 | "suggest": { 2651 | "ext-intl": "For best performance" 2652 | }, 2653 | "type": "library", 2654 | "extra": { 2655 | "branch-alias": { 2656 | "dev-main": "1.28-dev" 2657 | }, 2658 | "thanks": { 2659 | "name": "symfony/polyfill", 2660 | "url": "https://github.com/symfony/polyfill" 2661 | } 2662 | }, 2663 | "autoload": { 2664 | "files": [ 2665 | "bootstrap.php" 2666 | ], 2667 | "psr-4": { 2668 | "Symfony\\Polyfill\\Intl\\Grapheme\\": "" 2669 | } 2670 | }, 2671 | "notification-url": "https://packagist.org/downloads/", 2672 | "license": [ 2673 | "MIT" 2674 | ], 2675 | "authors": [ 2676 | { 2677 | "name": "Nicolas Grekas", 2678 | "email": "p@tchwork.com" 2679 | }, 2680 | { 2681 | "name": "Symfony Community", 2682 | "homepage": "https://symfony.com/contributors" 2683 | } 2684 | ], 2685 | "description": "Symfony polyfill for intl's grapheme_* functions", 2686 | "homepage": "https://symfony.com", 2687 | "keywords": [ 2688 | "compatibility", 2689 | "grapheme", 2690 | "intl", 2691 | "polyfill", 2692 | "portable", 2693 | "shim" 2694 | ], 2695 | "funding": [ 2696 | { 2697 | "url": "https://symfony.com/sponsor", 2698 | "type": "custom" 2699 | }, 2700 | { 2701 | "url": "https://github.com/fabpot", 2702 | "type": "github" 2703 | }, 2704 | { 2705 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2706 | "type": "tidelift" 2707 | } 2708 | ], 2709 | "time": "2023-01-26T09:26:14+00:00" 2710 | }, 2711 | { 2712 | "name": "symfony/polyfill-intl-normalizer", 2713 | "version": "v1.28.0", 2714 | "source": { 2715 | "type": "git", 2716 | "url": "https://github.com/symfony/polyfill-intl-normalizer.git", 2717 | "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" 2718 | }, 2719 | "dist": { 2720 | "type": "zip", 2721 | "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", 2722 | "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", 2723 | "shasum": "" 2724 | }, 2725 | "require": { 2726 | "php": ">=7.1" 2727 | }, 2728 | "suggest": { 2729 | "ext-intl": "For best performance" 2730 | }, 2731 | "type": "library", 2732 | "extra": { 2733 | "branch-alias": { 2734 | "dev-main": "1.28-dev" 2735 | }, 2736 | "thanks": { 2737 | "name": "symfony/polyfill", 2738 | "url": "https://github.com/symfony/polyfill" 2739 | } 2740 | }, 2741 | "autoload": { 2742 | "files": [ 2743 | "bootstrap.php" 2744 | ], 2745 | "psr-4": { 2746 | "Symfony\\Polyfill\\Intl\\Normalizer\\": "" 2747 | }, 2748 | "classmap": [ 2749 | "Resources/stubs" 2750 | ] 2751 | }, 2752 | "notification-url": "https://packagist.org/downloads/", 2753 | "license": [ 2754 | "MIT" 2755 | ], 2756 | "authors": [ 2757 | { 2758 | "name": "Nicolas Grekas", 2759 | "email": "p@tchwork.com" 2760 | }, 2761 | { 2762 | "name": "Symfony Community", 2763 | "homepage": "https://symfony.com/contributors" 2764 | } 2765 | ], 2766 | "description": "Symfony polyfill for intl's Normalizer class and related functions", 2767 | "homepage": "https://symfony.com", 2768 | "keywords": [ 2769 | "compatibility", 2770 | "intl", 2771 | "normalizer", 2772 | "polyfill", 2773 | "portable", 2774 | "shim" 2775 | ], 2776 | "funding": [ 2777 | { 2778 | "url": "https://symfony.com/sponsor", 2779 | "type": "custom" 2780 | }, 2781 | { 2782 | "url": "https://github.com/fabpot", 2783 | "type": "github" 2784 | }, 2785 | { 2786 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2787 | "type": "tidelift" 2788 | } 2789 | ], 2790 | "time": "2023-01-26T09:26:14+00:00" 2791 | }, 2792 | { 2793 | "name": "symfony/polyfill-mbstring", 2794 | "version": "v1.28.0", 2795 | "source": { 2796 | "type": "git", 2797 | "url": "https://github.com/symfony/polyfill-mbstring.git", 2798 | "reference": "42292d99c55abe617799667f454222c54c60e229" 2799 | }, 2800 | "dist": { 2801 | "type": "zip", 2802 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", 2803 | "reference": "42292d99c55abe617799667f454222c54c60e229", 2804 | "shasum": "" 2805 | }, 2806 | "require": { 2807 | "php": ">=7.1" 2808 | }, 2809 | "provide": { 2810 | "ext-mbstring": "*" 2811 | }, 2812 | "suggest": { 2813 | "ext-mbstring": "For best performance" 2814 | }, 2815 | "type": "library", 2816 | "extra": { 2817 | "branch-alias": { 2818 | "dev-main": "1.28-dev" 2819 | }, 2820 | "thanks": { 2821 | "name": "symfony/polyfill", 2822 | "url": "https://github.com/symfony/polyfill" 2823 | } 2824 | }, 2825 | "autoload": { 2826 | "files": [ 2827 | "bootstrap.php" 2828 | ], 2829 | "psr-4": { 2830 | "Symfony\\Polyfill\\Mbstring\\": "" 2831 | } 2832 | }, 2833 | "notification-url": "https://packagist.org/downloads/", 2834 | "license": [ 2835 | "MIT" 2836 | ], 2837 | "authors": [ 2838 | { 2839 | "name": "Nicolas Grekas", 2840 | "email": "p@tchwork.com" 2841 | }, 2842 | { 2843 | "name": "Symfony Community", 2844 | "homepage": "https://symfony.com/contributors" 2845 | } 2846 | ], 2847 | "description": "Symfony polyfill for the Mbstring extension", 2848 | "homepage": "https://symfony.com", 2849 | "keywords": [ 2850 | "compatibility", 2851 | "mbstring", 2852 | "polyfill", 2853 | "portable", 2854 | "shim" 2855 | ], 2856 | "funding": [ 2857 | { 2858 | "url": "https://symfony.com/sponsor", 2859 | "type": "custom" 2860 | }, 2861 | { 2862 | "url": "https://github.com/fabpot", 2863 | "type": "github" 2864 | }, 2865 | { 2866 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2867 | "type": "tidelift" 2868 | } 2869 | ], 2870 | "time": "2023-07-28T09:04:16+00:00" 2871 | }, 2872 | { 2873 | "name": "symfony/polyfill-php73", 2874 | "version": "v1.28.0", 2875 | "source": { 2876 | "type": "git", 2877 | "url": "https://github.com/symfony/polyfill-php73.git", 2878 | "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5" 2879 | }, 2880 | "dist": { 2881 | "type": "zip", 2882 | "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fe2f306d1d9d346a7fee353d0d5012e401e984b5", 2883 | "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5", 2884 | "shasum": "" 2885 | }, 2886 | "require": { 2887 | "php": ">=7.1" 2888 | }, 2889 | "type": "library", 2890 | "extra": { 2891 | "branch-alias": { 2892 | "dev-main": "1.28-dev" 2893 | }, 2894 | "thanks": { 2895 | "name": "symfony/polyfill", 2896 | "url": "https://github.com/symfony/polyfill" 2897 | } 2898 | }, 2899 | "autoload": { 2900 | "files": [ 2901 | "bootstrap.php" 2902 | ], 2903 | "psr-4": { 2904 | "Symfony\\Polyfill\\Php73\\": "" 2905 | }, 2906 | "classmap": [ 2907 | "Resources/stubs" 2908 | ] 2909 | }, 2910 | "notification-url": "https://packagist.org/downloads/", 2911 | "license": [ 2912 | "MIT" 2913 | ], 2914 | "authors": [ 2915 | { 2916 | "name": "Nicolas Grekas", 2917 | "email": "p@tchwork.com" 2918 | }, 2919 | { 2920 | "name": "Symfony Community", 2921 | "homepage": "https://symfony.com/contributors" 2922 | } 2923 | ], 2924 | "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", 2925 | "homepage": "https://symfony.com", 2926 | "keywords": [ 2927 | "compatibility", 2928 | "polyfill", 2929 | "portable", 2930 | "shim" 2931 | ], 2932 | "funding": [ 2933 | { 2934 | "url": "https://symfony.com/sponsor", 2935 | "type": "custom" 2936 | }, 2937 | { 2938 | "url": "https://github.com/fabpot", 2939 | "type": "github" 2940 | }, 2941 | { 2942 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2943 | "type": "tidelift" 2944 | } 2945 | ], 2946 | "time": "2023-01-26T09:26:14+00:00" 2947 | }, 2948 | { 2949 | "name": "symfony/polyfill-php80", 2950 | "version": "v1.28.0", 2951 | "source": { 2952 | "type": "git", 2953 | "url": "https://github.com/symfony/polyfill-php80.git", 2954 | "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" 2955 | }, 2956 | "dist": { 2957 | "type": "zip", 2958 | "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", 2959 | "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", 2960 | "shasum": "" 2961 | }, 2962 | "require": { 2963 | "php": ">=7.1" 2964 | }, 2965 | "type": "library", 2966 | "extra": { 2967 | "branch-alias": { 2968 | "dev-main": "1.28-dev" 2969 | }, 2970 | "thanks": { 2971 | "name": "symfony/polyfill", 2972 | "url": "https://github.com/symfony/polyfill" 2973 | } 2974 | }, 2975 | "autoload": { 2976 | "files": [ 2977 | "bootstrap.php" 2978 | ], 2979 | "psr-4": { 2980 | "Symfony\\Polyfill\\Php80\\": "" 2981 | }, 2982 | "classmap": [ 2983 | "Resources/stubs" 2984 | ] 2985 | }, 2986 | "notification-url": "https://packagist.org/downloads/", 2987 | "license": [ 2988 | "MIT" 2989 | ], 2990 | "authors": [ 2991 | { 2992 | "name": "Ion Bazan", 2993 | "email": "ion.bazan@gmail.com" 2994 | }, 2995 | { 2996 | "name": "Nicolas Grekas", 2997 | "email": "p@tchwork.com" 2998 | }, 2999 | { 3000 | "name": "Symfony Community", 3001 | "homepage": "https://symfony.com/contributors" 3002 | } 3003 | ], 3004 | "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", 3005 | "homepage": "https://symfony.com", 3006 | "keywords": [ 3007 | "compatibility", 3008 | "polyfill", 3009 | "portable", 3010 | "shim" 3011 | ], 3012 | "funding": [ 3013 | { 3014 | "url": "https://symfony.com/sponsor", 3015 | "type": "custom" 3016 | }, 3017 | { 3018 | "url": "https://github.com/fabpot", 3019 | "type": "github" 3020 | }, 3021 | { 3022 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3023 | "type": "tidelift" 3024 | } 3025 | ], 3026 | "time": "2023-01-26T09:26:14+00:00" 3027 | }, 3028 | { 3029 | "name": "symfony/polyfill-php81", 3030 | "version": "v1.28.0", 3031 | "source": { 3032 | "type": "git", 3033 | "url": "https://github.com/symfony/polyfill-php81.git", 3034 | "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" 3035 | }, 3036 | "dist": { 3037 | "type": "zip", 3038 | "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", 3039 | "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", 3040 | "shasum": "" 3041 | }, 3042 | "require": { 3043 | "php": ">=7.1" 3044 | }, 3045 | "type": "library", 3046 | "extra": { 3047 | "branch-alias": { 3048 | "dev-main": "1.28-dev" 3049 | }, 3050 | "thanks": { 3051 | "name": "symfony/polyfill", 3052 | "url": "https://github.com/symfony/polyfill" 3053 | } 3054 | }, 3055 | "autoload": { 3056 | "files": [ 3057 | "bootstrap.php" 3058 | ], 3059 | "psr-4": { 3060 | "Symfony\\Polyfill\\Php81\\": "" 3061 | }, 3062 | "classmap": [ 3063 | "Resources/stubs" 3064 | ] 3065 | }, 3066 | "notification-url": "https://packagist.org/downloads/", 3067 | "license": [ 3068 | "MIT" 3069 | ], 3070 | "authors": [ 3071 | { 3072 | "name": "Nicolas Grekas", 3073 | "email": "p@tchwork.com" 3074 | }, 3075 | { 3076 | "name": "Symfony Community", 3077 | "homepage": "https://symfony.com/contributors" 3078 | } 3079 | ], 3080 | "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", 3081 | "homepage": "https://symfony.com", 3082 | "keywords": [ 3083 | "compatibility", 3084 | "polyfill", 3085 | "portable", 3086 | "shim" 3087 | ], 3088 | "funding": [ 3089 | { 3090 | "url": "https://symfony.com/sponsor", 3091 | "type": "custom" 3092 | }, 3093 | { 3094 | "url": "https://github.com/fabpot", 3095 | "type": "github" 3096 | }, 3097 | { 3098 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3099 | "type": "tidelift" 3100 | } 3101 | ], 3102 | "time": "2023-01-26T09:26:14+00:00" 3103 | }, 3104 | { 3105 | "name": "symfony/service-contracts", 3106 | "version": "v2.5.2", 3107 | "source": { 3108 | "type": "git", 3109 | "url": "https://github.com/symfony/service-contracts.git", 3110 | "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" 3111 | }, 3112 | "dist": { 3113 | "type": "zip", 3114 | "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", 3115 | "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", 3116 | "shasum": "" 3117 | }, 3118 | "require": { 3119 | "php": ">=7.2.5", 3120 | "psr/container": "^1.1", 3121 | "symfony/deprecation-contracts": "^2.1|^3" 3122 | }, 3123 | "conflict": { 3124 | "ext-psr": "<1.1|>=2" 3125 | }, 3126 | "suggest": { 3127 | "symfony/service-implementation": "" 3128 | }, 3129 | "type": "library", 3130 | "extra": { 3131 | "branch-alias": { 3132 | "dev-main": "2.5-dev" 3133 | }, 3134 | "thanks": { 3135 | "name": "symfony/contracts", 3136 | "url": "https://github.com/symfony/contracts" 3137 | } 3138 | }, 3139 | "autoload": { 3140 | "psr-4": { 3141 | "Symfony\\Contracts\\Service\\": "" 3142 | } 3143 | }, 3144 | "notification-url": "https://packagist.org/downloads/", 3145 | "license": [ 3146 | "MIT" 3147 | ], 3148 | "authors": [ 3149 | { 3150 | "name": "Nicolas Grekas", 3151 | "email": "p@tchwork.com" 3152 | }, 3153 | { 3154 | "name": "Symfony Community", 3155 | "homepage": "https://symfony.com/contributors" 3156 | } 3157 | ], 3158 | "description": "Generic abstractions related to writing services", 3159 | "homepage": "https://symfony.com", 3160 | "keywords": [ 3161 | "abstractions", 3162 | "contracts", 3163 | "decoupling", 3164 | "interfaces", 3165 | "interoperability", 3166 | "standards" 3167 | ], 3168 | "funding": [ 3169 | { 3170 | "url": "https://symfony.com/sponsor", 3171 | "type": "custom" 3172 | }, 3173 | { 3174 | "url": "https://github.com/fabpot", 3175 | "type": "github" 3176 | }, 3177 | { 3178 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3179 | "type": "tidelift" 3180 | } 3181 | ], 3182 | "time": "2022-05-30T19:17:29+00:00" 3183 | }, 3184 | { 3185 | "name": "symfony/stopwatch", 3186 | "version": "v5.4.21", 3187 | "source": { 3188 | "type": "git", 3189 | "url": "https://github.com/symfony/stopwatch.git", 3190 | "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee" 3191 | }, 3192 | "dist": { 3193 | "type": "zip", 3194 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee", 3195 | "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee", 3196 | "shasum": "" 3197 | }, 3198 | "require": { 3199 | "php": ">=7.2.5", 3200 | "symfony/service-contracts": "^1|^2|^3" 3201 | }, 3202 | "type": "library", 3203 | "autoload": { 3204 | "psr-4": { 3205 | "Symfony\\Component\\Stopwatch\\": "" 3206 | }, 3207 | "exclude-from-classmap": [ 3208 | "/Tests/" 3209 | ] 3210 | }, 3211 | "notification-url": "https://packagist.org/downloads/", 3212 | "license": [ 3213 | "MIT" 3214 | ], 3215 | "authors": [ 3216 | { 3217 | "name": "Fabien Potencier", 3218 | "email": "fabien@symfony.com" 3219 | }, 3220 | { 3221 | "name": "Symfony Community", 3222 | "homepage": "https://symfony.com/contributors" 3223 | } 3224 | ], 3225 | "description": "Provides a way to profile code", 3226 | "homepage": "https://symfony.com", 3227 | "funding": [ 3228 | { 3229 | "url": "https://symfony.com/sponsor", 3230 | "type": "custom" 3231 | }, 3232 | { 3233 | "url": "https://github.com/fabpot", 3234 | "type": "github" 3235 | }, 3236 | { 3237 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3238 | "type": "tidelift" 3239 | } 3240 | ], 3241 | "time": "2023-02-14T08:03:56+00:00" 3242 | }, 3243 | { 3244 | "name": "symfony/string", 3245 | "version": "v5.4.31", 3246 | "source": { 3247 | "type": "git", 3248 | "url": "https://github.com/symfony/string.git", 3249 | "reference": "2765096c03f39ddf54f6af532166e42aaa05b24b" 3250 | }, 3251 | "dist": { 3252 | "type": "zip", 3253 | "url": "https://api.github.com/repos/symfony/string/zipball/2765096c03f39ddf54f6af532166e42aaa05b24b", 3254 | "reference": "2765096c03f39ddf54f6af532166e42aaa05b24b", 3255 | "shasum": "" 3256 | }, 3257 | "require": { 3258 | "php": ">=7.2.5", 3259 | "symfony/polyfill-ctype": "~1.8", 3260 | "symfony/polyfill-intl-grapheme": "~1.0", 3261 | "symfony/polyfill-intl-normalizer": "~1.0", 3262 | "symfony/polyfill-mbstring": "~1.0", 3263 | "symfony/polyfill-php80": "~1.15" 3264 | }, 3265 | "conflict": { 3266 | "symfony/translation-contracts": ">=3.0" 3267 | }, 3268 | "require-dev": { 3269 | "symfony/error-handler": "^4.4|^5.0|^6.0", 3270 | "symfony/http-client": "^4.4|^5.0|^6.0", 3271 | "symfony/translation-contracts": "^1.1|^2", 3272 | "symfony/var-exporter": "^4.4|^5.0|^6.0" 3273 | }, 3274 | "type": "library", 3275 | "autoload": { 3276 | "files": [ 3277 | "Resources/functions.php" 3278 | ], 3279 | "psr-4": { 3280 | "Symfony\\Component\\String\\": "" 3281 | }, 3282 | "exclude-from-classmap": [ 3283 | "/Tests/" 3284 | ] 3285 | }, 3286 | "notification-url": "https://packagist.org/downloads/", 3287 | "license": [ 3288 | "MIT" 3289 | ], 3290 | "authors": [ 3291 | { 3292 | "name": "Nicolas Grekas", 3293 | "email": "p@tchwork.com" 3294 | }, 3295 | { 3296 | "name": "Symfony Community", 3297 | "homepage": "https://symfony.com/contributors" 3298 | } 3299 | ], 3300 | "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", 3301 | "homepage": "https://symfony.com", 3302 | "keywords": [ 3303 | "grapheme", 3304 | "i18n", 3305 | "string", 3306 | "unicode", 3307 | "utf-8", 3308 | "utf8" 3309 | ], 3310 | "funding": [ 3311 | { 3312 | "url": "https://symfony.com/sponsor", 3313 | "type": "custom" 3314 | }, 3315 | { 3316 | "url": "https://github.com/fabpot", 3317 | "type": "github" 3318 | }, 3319 | { 3320 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3321 | "type": "tidelift" 3322 | } 3323 | ], 3324 | "time": "2023-11-09T08:19:44+00:00" 3325 | }, 3326 | { 3327 | "name": "symfony/yaml", 3328 | "version": "v5.4.31", 3329 | "source": { 3330 | "type": "git", 3331 | "url": "https://github.com/symfony/yaml.git", 3332 | "reference": "f387675d7f5fc4231f7554baa70681f222f73563" 3333 | }, 3334 | "dist": { 3335 | "type": "zip", 3336 | "url": "https://api.github.com/repos/symfony/yaml/zipball/f387675d7f5fc4231f7554baa70681f222f73563", 3337 | "reference": "f387675d7f5fc4231f7554baa70681f222f73563", 3338 | "shasum": "" 3339 | }, 3340 | "require": { 3341 | "php": ">=7.2.5", 3342 | "symfony/deprecation-contracts": "^2.1|^3", 3343 | "symfony/polyfill-ctype": "^1.8" 3344 | }, 3345 | "conflict": { 3346 | "symfony/console": "<5.3" 3347 | }, 3348 | "require-dev": { 3349 | "symfony/console": "^5.3|^6.0" 3350 | }, 3351 | "suggest": { 3352 | "symfony/console": "For validating YAML files using the lint command" 3353 | }, 3354 | "bin": [ 3355 | "Resources/bin/yaml-lint" 3356 | ], 3357 | "type": "library", 3358 | "autoload": { 3359 | "psr-4": { 3360 | "Symfony\\Component\\Yaml\\": "" 3361 | }, 3362 | "exclude-from-classmap": [ 3363 | "/Tests/" 3364 | ] 3365 | }, 3366 | "notification-url": "https://packagist.org/downloads/", 3367 | "license": [ 3368 | "MIT" 3369 | ], 3370 | "authors": [ 3371 | { 3372 | "name": "Fabien Potencier", 3373 | "email": "fabien@symfony.com" 3374 | }, 3375 | { 3376 | "name": "Symfony Community", 3377 | "homepage": "https://symfony.com/contributors" 3378 | } 3379 | ], 3380 | "description": "Loads and dumps YAML files", 3381 | "homepage": "https://symfony.com", 3382 | "funding": [ 3383 | { 3384 | "url": "https://symfony.com/sponsor", 3385 | "type": "custom" 3386 | }, 3387 | { 3388 | "url": "https://github.com/fabpot", 3389 | "type": "github" 3390 | }, 3391 | { 3392 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3393 | "type": "tidelift" 3394 | } 3395 | ], 3396 | "time": "2023-11-03T14:41:28+00:00" 3397 | }, 3398 | { 3399 | "name": "theseer/tokenizer", 3400 | "version": "1.2.1", 3401 | "source": { 3402 | "type": "git", 3403 | "url": "https://github.com/theseer/tokenizer.git", 3404 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" 3405 | }, 3406 | "dist": { 3407 | "type": "zip", 3408 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", 3409 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", 3410 | "shasum": "" 3411 | }, 3412 | "require": { 3413 | "ext-dom": "*", 3414 | "ext-tokenizer": "*", 3415 | "ext-xmlwriter": "*", 3416 | "php": "^7.2 || ^8.0" 3417 | }, 3418 | "type": "library", 3419 | "autoload": { 3420 | "classmap": [ 3421 | "src/" 3422 | ] 3423 | }, 3424 | "notification-url": "https://packagist.org/downloads/", 3425 | "license": [ 3426 | "BSD-3-Clause" 3427 | ], 3428 | "authors": [ 3429 | { 3430 | "name": "Arne Blankerts", 3431 | "email": "arne@blankerts.de", 3432 | "role": "Developer" 3433 | } 3434 | ], 3435 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 3436 | "funding": [ 3437 | { 3438 | "url": "https://github.com/theseer", 3439 | "type": "github" 3440 | } 3441 | ], 3442 | "time": "2021-07-28T10:34:58+00:00" 3443 | } 3444 | ], 3445 | "aliases": [], 3446 | "minimum-stability": "stable", 3447 | "stability-flags": [], 3448 | "prefer-stable": false, 3449 | "prefer-lowest": false, 3450 | "platform": { 3451 | "php": ">=7.3", 3452 | "ext-json": "*" 3453 | }, 3454 | "platform-dev": [], 3455 | "plugin-api-version": "1.1.0" 3456 | } 3457 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/DriverFactory.php: -------------------------------------------------------------------------------- 1 | MockCurrencyDriver::class, 22 | 'fixerio' => FixerIo::class, 23 | 'currencylayer' => CurrencyLayer::class, 24 | 'openexchangerates' => OpenExchangeRates::class, 25 | 'exchangeratesapi' => ExchangeRatesApi::class, 26 | ]; 27 | 28 | /** 29 | * @param string $name 30 | * @param ClientInterface|null $client 31 | * 32 | * @return CurrencyDriverContract 33 | * 34 | * @throws DriverNotFoundException 35 | */ 36 | public static function make(string $name, ClientInterface $client = null): CurrencyDriverContract 37 | { 38 | if (!isset(static::DRIVERS[$name])) { 39 | throw new DriverNotFoundException("{$name} is not a valid driver."); 40 | } 41 | 42 | $class = static::DRIVERS[$name]; 43 | 44 | // If no client is specified, create a HTTPClient instance. 45 | $client = $client == null ? new HTTPClient() : $client; 46 | return new $class($client); 47 | } 48 | 49 | /** 50 | * Get all of the available drivers. 51 | * 52 | * @return array 53 | */ 54 | public static function getDrivers(): array 55 | { 56 | return self::DRIVERS; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Drivers/BaseCurrencyDriver.php: -------------------------------------------------------------------------------- 1 | 'application/json', 23 | 'Content-Type' => 'application/json', 24 | ]; 25 | 26 | protected $currencies = []; 27 | protected $baseCurrency = 'USD'; 28 | protected $amount = 0.00; 29 | protected $date = null; 30 | 31 | protected $httpClient = null; 32 | protected $httpParams = []; 33 | 34 | /** 35 | * BaseDriver constructor. 36 | * 37 | * @param ClientInterface $client 38 | */ 39 | public function __construct(ClientInterface $client) 40 | { 41 | $this->httpClient = $client; 42 | } 43 | 44 | /** 45 | * @param string $baseCurrency 46 | * 47 | * @return self 48 | */ 49 | public function source(string $baseCurrency): CurrencyDriverContract 50 | { 51 | $this->baseCurrency = $baseCurrency; 52 | return $this; 53 | } 54 | 55 | /** 56 | * Alias for 'source'. 57 | * 58 | * @param string $baseCurrency 59 | * 60 | * @return CurrencyDriverContract 61 | * @see CurrencyDriverContract::source() 62 | * 63 | */ 64 | public function from(string $baseCurrency): CurrencyDriverContract 65 | { 66 | return $this->source($baseCurrency); 67 | } 68 | 69 | /** 70 | * @param string|array $symbols 71 | * 72 | * @return self 73 | */ 74 | public function currencies($symbols = []): CurrencyDriverContract 75 | { 76 | $this->currencies = (array)$symbols; 77 | return $this; 78 | } 79 | 80 | /** 81 | * Alias for 'currencies'. 82 | * 83 | * @param array $symbols 84 | * 85 | * @return CurrencyDriverContract 86 | * @see CurrencyDriverContract::currencies() 87 | * 88 | */ 89 | public function to($symbols = []): CurrencyDriverContract 90 | { 91 | return $this->currencies($symbols); 92 | } 93 | 94 | /** 95 | * @param double|integer|float $amount 96 | * 97 | * @return self 98 | */ 99 | public function amount($amount): CurrencyDriverContract 100 | { 101 | $this->amount = $amount; 102 | return $this; 103 | } 104 | 105 | /** 106 | * @param int|string|DateTime|DateInterval|DateTimeInterface $date 107 | * 108 | * @return self 109 | * 110 | * @throws Exception 111 | */ 112 | public function date($date): CurrencyDriverContract 113 | { 114 | if ($date === null) { 115 | return $this; 116 | } 117 | 118 | $this->date = DateHelper::format($date, 'Y-m-d'); 119 | return $this; 120 | } 121 | 122 | /** 123 | * Returns the date in 'YYYY-mm-dd' format or null if not set. 124 | * 125 | * @return string|null 126 | */ 127 | public function getDate(): ?string 128 | { 129 | return $this->date; 130 | } 131 | 132 | /** 133 | * @return array 134 | */ 135 | public function getSymbols(): array 136 | { 137 | return $this->currencies; 138 | } 139 | 140 | /** 141 | * @return string 142 | */ 143 | public function getBaseCurrency(): string 144 | { 145 | return $this->baseCurrency; 146 | } 147 | 148 | /** 149 | * @return self 150 | */ 151 | public function secure(): CurrencyDriverContract 152 | { 153 | $this->protocol = 'https'; 154 | return $this; 155 | } 156 | 157 | /** 158 | * @return string 159 | */ 160 | public function getProtocol(): string 161 | { 162 | return $this->protocol; 163 | } 164 | 165 | /** 166 | * Set a config parameter. 167 | * 168 | * @param string $key 169 | * @param string $value 170 | * 171 | * @return self 172 | */ 173 | public function config(string $key, string $value): CurrencyDriverContract 174 | { 175 | $this->httpParams[$key] = $value; 176 | return $this; 177 | } 178 | 179 | /** 180 | * Sets the API key to use. 181 | * 182 | * Shortcut for config('access_key', $accessKey) 183 | * 184 | * @param string $accessKey Your API key. 185 | * 186 | * @return self 187 | * @see CurrencyDriverContract::config() 188 | * 189 | */ 190 | public function accessKey(string $accessKey): CurrencyDriverContract 191 | { 192 | $this->config('access_key', $accessKey); 193 | return $this; 194 | } 195 | 196 | /** 197 | * Performs an HTTP request. 198 | * 199 | * @param string $endpoint The API endpoint. 200 | * @param array $params The query parameters for this request. 201 | * @param string $method The HTTP method (defaults to 'GET'). 202 | * 203 | * @return array|bool The response as decoded JSON. 204 | * 205 | * @throws ApiException 206 | */ 207 | function apiRequest(string $endpoint, array $params = [], string $method = 'GET') 208 | { 209 | $url = sprintf('%s://%s/%s', $this->getProtocol(), $this->apiURL, $endpoint); 210 | 211 | try { 212 | $response = $this->httpClient->request($method, $url, ['query' => array_merge($this->httpParams, $params)])->getBody(); 213 | } catch (GuzzleException $e) { 214 | throw new ApiException($e->getMessage(), $e->getCode(), $e); 215 | } 216 | 217 | $data = json_decode($response->getContents(), true); 218 | 219 | // Check for JSON errors 220 | if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) { 221 | throw new ApiException(json_last_error_msg(), json_last_error()); 222 | } 223 | 224 | // Otherwise return data. 225 | return $data; 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /src/Drivers/CurrencyDriverContract.php: -------------------------------------------------------------------------------- 1 | 0, 24 | ]; 25 | 26 | /** 27 | * @param string|array $forCurrency 28 | * 29 | * @return ConversionResult 30 | * 31 | * @throws CurrencyException 32 | */ 33 | public function get($forCurrency = []): ConversionResult 34 | { 35 | if (!empty((array)$forCurrency)) { 36 | $this->currencies((array)$forCurrency); 37 | } 38 | 39 | // Get API response 40 | $response = $this->apiRequest('live', [ 41 | 'source' => $this->getBaseCurrency(), 42 | 'currencies' => join(',', $this->getSymbols()), 43 | ]); 44 | 45 | // Transform rates response 46 | $rates = []; 47 | foreach ($response['quotes'] as $currency => $rate) { 48 | $rates[substr($currency, 3, 3)] = $rate; 49 | } 50 | 51 | return new ConversionResult($response['source'], $response['timestamp'], $rates); 52 | } 53 | 54 | /** 55 | * @param int|string|DateTime $date 56 | * @param string|array $forCurrency 57 | * 58 | * @return ConversionResult 59 | * 60 | * @throws CurrencyException 61 | */ 62 | public function historical($date = null, $forCurrency = []): ConversionResult 63 | { 64 | // Set date 65 | $this->date($date); 66 | 67 | if (!empty((array)$forCurrency)) { 68 | $this->currencies((array)$forCurrency); 69 | } 70 | 71 | if (null === $this->getDate()) { 72 | throw new ApiException('Date needs to be set!'); 73 | } 74 | 75 | // Get API response 76 | $response = $this->apiRequest('historical', [ 77 | 'date' => $this->getDate(), 78 | 'source' => $this->getBaseCurrency(), 79 | 'currencies' => join(',', $this->getSymbols()), 80 | ]); 81 | 82 | // Transform rates response 83 | $rates = []; 84 | foreach ($response['quotes'] as $currency => $rate) { 85 | $rates[substr($currency, 3, 3)] = $rate; 86 | } 87 | 88 | return new ConversionResult($response['source'], $response['timestamp'], $rates); 89 | } 90 | 91 | /** 92 | * Converts any amount in a given currency to another currency. 93 | * 94 | * @param float $amount The amount to convert. 95 | * @param string $fromCurrency The base currency. 96 | * @param string $toCurrency The target currency. 97 | * @param int|string|DateTime $date The date to get the conversion rate for. 98 | * 99 | * @return float The conversion result. 100 | * 101 | * @throws ApiException 102 | */ 103 | public function convert(float $amount = null, string $fromCurrency = null, string $toCurrency = null, $date = null): float 104 | { 105 | $this->date($date); 106 | 107 | // Overwrite/set params 108 | if ($amount !== null) { 109 | $this->amount = $amount; 110 | } 111 | 112 | if ($fromCurrency !== null) { 113 | $this->baseCurrency = $fromCurrency; 114 | } 115 | 116 | if ($toCurrency !== null) { 117 | $this->currencies = [$toCurrency]; 118 | } 119 | 120 | $params = [ 121 | 'from' => $this->getBaseCurrency(), 122 | 'to' => reset($this->currencies), 123 | 'amount' => $this->amount, 124 | ]; 125 | 126 | if (null !== $this->getDate()) { 127 | $params['date'] = $this->getDate(); 128 | } 129 | 130 | // Get API response 131 | $response = $this->apiRequest('convert', $params); 132 | 133 | // Return the rate as a float 134 | return floatval($response['result']); 135 | } 136 | 137 | /** 138 | * Performs an HTTP request. 139 | * 140 | * @param string $endpoint The API endpoint. 141 | * @param array $params The query parameters for this request. 142 | * @param string $method The HTTP method (defaults to 'GET'). 143 | * 144 | * @return array|bool The response as decoded JSON. 145 | * 146 | * @throws ApiException 147 | */ 148 | function apiRequest(string $endpoint, array $params = [], string $method = 'GET') 149 | { 150 | // Perform actual API request. 151 | $response = parent::apiRequest($endpoint, $params, $method); 152 | 153 | // Handle response exceptions. 154 | if ($response['success'] == false) { 155 | throw new ApiException($response['error']['info'], $response['error']['code']); 156 | } 157 | 158 | return $response; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/Drivers/ExchangeRatesApi.php: -------------------------------------------------------------------------------- 1 | currencies((array)$forCurrency); 46 | } 47 | 48 | // Get API response 49 | $response = $this->apiRequest('latest', [ 50 | 'base' => $this->getBaseCurrency(), 51 | 'symbols' => join(',', $this->getSymbols()), 52 | ]); 53 | 54 | return new ConversionResult($response['base'], $response['date'], $response['rates']); 55 | } 56 | 57 | /** 58 | * @param int|string|DateTime $date 59 | * @param string|array $forCurrency 60 | * 61 | * @return ConversionResult 62 | * 63 | * @throws CurrencyException 64 | */ 65 | public function historical($date = null, $forCurrency = []): ConversionResult 66 | { 67 | // Set date 68 | $this->date($date); 69 | 70 | if (!empty((array)$forCurrency)) { 71 | $this->currencies((array)$forCurrency); 72 | } 73 | 74 | if (null === $this->getDate()) { 75 | throw new ApiException('Date needs to be set!'); 76 | } 77 | 78 | // Get API response 79 | $response = $this->apiRequest($this->getDate(), [ 80 | 'base' => $this->getBaseCurrency(), 81 | 'symbols' => join(',', $this->getSymbols()), 82 | ]); 83 | 84 | return new ConversionResult($response['base'], $response['date'], $response['rates']); 85 | } 86 | 87 | /** 88 | * Converts any amount in a given currency to another currency. 89 | * 90 | * @param float $amount The amount to convert. 91 | * @param string $fromCurrency The base currency. 92 | * @param string $toCurrency The target currency. 93 | * @param int|string|DateTime $date The date to get the conversion rate for. 94 | * 95 | * @return float The conversion result. 96 | * 97 | * @throws ApiException 98 | */ 99 | public function convert(float $amount = null, string $fromCurrency = null, string $toCurrency = null, $date = null): float 100 | { 101 | throw new ApiException("Endpoint 'convert' is not supported for this driver!", 404); 102 | } 103 | 104 | /** 105 | * Performs an HTTP request. 106 | * 107 | * @param string $endpoint The API endpoint. 108 | * @param array $params The query parameters for this request. 109 | * @param string $method The HTTP method (defaults to 'GET'). 110 | * 111 | * @return array|bool The response as decoded JSON. 112 | * 113 | * @throws ApiException 114 | */ 115 | function apiRequest(string $endpoint, array $params = [], string $method = 'GET') 116 | { 117 | // Perform actual API request. 118 | $response = parent::apiRequest($endpoint, $params, $method); 119 | 120 | 121 | // Handle response exceptions. 122 | if (isset($response['error'])) { 123 | throw new ApiException((string)$response['error'], 500); 124 | } 125 | 126 | return $response; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/Drivers/FixerIo.php: -------------------------------------------------------------------------------- 1 | currencies((array)$forCurrency); 34 | } 35 | 36 | // Get API response 37 | $response = $this->apiRequest('latest', [ 38 | 'base' => $this->getBaseCurrency(), 39 | 'symbols' => join(',', $this->getSymbols()), 40 | ]); 41 | 42 | return new ConversionResult($response['base'], $response['date'], $response['rates']); 43 | } 44 | 45 | /** 46 | * @param int|string|DateTime $date 47 | * @param string|array $forCurrency 48 | * 49 | * @return ConversionResult 50 | * 51 | * @throws CurrencyException 52 | */ 53 | public function historical($date = null, $forCurrency = []): ConversionResult 54 | { 55 | // Set date 56 | $this->date($date); 57 | 58 | if (!empty((array)$forCurrency)) { 59 | $this->currencies((array)$forCurrency); 60 | } 61 | 62 | if (null === $this->getDate()) { 63 | throw new ApiException('Date needs to be set!'); 64 | } 65 | 66 | // Get API response 67 | $response = $this->apiRequest($this->getDate(), [ 68 | 'base' => $this->getBaseCurrency(), 69 | 'symbols' => join(',', $this->getSymbols()), 70 | ]); 71 | 72 | return new ConversionResult($response['base'], $response['date'], $response['rates']); 73 | } 74 | 75 | /** 76 | * Converts any amount in a given currency to another currency. 77 | * 78 | * @param float $amount The amount to convert. 79 | * @param string $fromCurrency The base currency. 80 | * @param string $toCurrency The target currency. 81 | * @param int|string|DateTime $date The date to get the conversion rate for. 82 | * 83 | * @return float The conversion result. 84 | * 85 | * @throws ApiException 86 | */ 87 | public function convert(float $amount = null, string $fromCurrency = null, string $toCurrency = null, $date = null): float 88 | { 89 | // Set date 90 | $this->date($date); 91 | 92 | // Overwrite/set params 93 | if ($amount !== null) { 94 | $this->amount = $amount; 95 | } 96 | 97 | if ($fromCurrency !== null) { 98 | $this->baseCurrency = $fromCurrency; 99 | } 100 | 101 | if ($toCurrency !== null) { 102 | $this->currencies = [$toCurrency]; 103 | } 104 | 105 | $params = [ 106 | 'from' => $this->getBaseCurrency(), 107 | 'to' => reset($this->currencies), 108 | 'amount' => $this->amount, 109 | ]; 110 | 111 | if (null !== $this->getDate()) { 112 | $params['date'] = $this->getDate(); 113 | } 114 | 115 | // Get API response 116 | $response = $this->apiRequest('convert', $params); 117 | 118 | // Return the rate as a float 119 | return floatval($response['result']); 120 | } 121 | 122 | /** 123 | * Performs an HTTP request. 124 | * 125 | * @param string $endpoint The API endpoint. 126 | * @param array $params The query parameters for this request. 127 | * @param string $method The HTTP method (defaults to 'GET'). 128 | * 129 | * @return array|bool The response as decoded JSON. 130 | * 131 | * @throws ApiException 132 | */ 133 | function apiRequest(string $endpoint, array $params = [], string $method = 'GET') 134 | { 135 | // Perform actual API request. 136 | $response = parent::apiRequest($endpoint, $params, $method); 137 | 138 | // Handle response exceptions. 139 | if ($response['success'] == false) { 140 | $message = ''; 141 | if (isset($response['error']['type'])) { 142 | $message = "[{$response['error']['type']}]"; 143 | } 144 | if (isset($response['error']['info'])) { 145 | $message .= ' ' . $response['error']['info']; 146 | } 147 | throw new ApiException(trim($message), $response['error']['code']); 148 | } 149 | 150 | return $response; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/Drivers/MockCurrencyDriver.php: -------------------------------------------------------------------------------- 1 | getBaseCurrency(), time(), []); 26 | } 27 | 28 | /** 29 | * Converts any amount in a given currency to another currency. 30 | * 31 | * @param float $amount The amount to convert. 32 | * @param string $fromCurrency The base currency. 33 | * @param string $toCurrency The target currency. 34 | * @param int|string|DateTime $date The date to get the conversion rate for. 35 | * 36 | * @return float The conversion result. 37 | */ 38 | public function convert(float $amount = null, string $fromCurrency = null, string $toCurrency = null, $date = null): float 39 | { 40 | return 12.34; 41 | } 42 | 43 | /** 44 | * @param int|string|DateTime $date 45 | * @param string|array $forCurrency 46 | * 47 | * @return ConversionResult 48 | */ 49 | function historical($date = null, $forCurrency = []): ConversionResult 50 | { 51 | return new ConversionResult($this->getBaseCurrency(), time(), []); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Drivers/OpenExchangeRates.php: -------------------------------------------------------------------------------- 1 | 'false', 24 | 'show_alternative' => 'true', 25 | ]; 26 | 27 | /** 28 | * Sets the API key to use. OpenExchangeRates uses app_id instead of access_key 29 | * 30 | * Shortcut for config('app_id', $accessKey) 31 | * 32 | * @param string $accessKey Your API key. 33 | * 34 | * @return self 35 | * @see CurrencyDriverContract::config() 36 | * 37 | */ 38 | public function accessKey(string $accessKey): CurrencyDriverContract 39 | { 40 | $this->config('app_id', $accessKey); 41 | return $this; 42 | } 43 | 44 | /** 45 | * @param string|array $forCurrency 46 | * 47 | * @return ConversionResult 48 | * 49 | * @throws CurrencyException 50 | */ 51 | public function get($forCurrency = []): ConversionResult 52 | { 53 | if (!empty((array)$forCurrency)) { 54 | $this->currencies((array)$forCurrency); 55 | } 56 | 57 | // Get API response 58 | $response = $this->apiRequest('latest.json', [ 59 | 'base' => $this->getBaseCurrency(), 60 | 'symbols' => join(',', $this->getSymbols()), 61 | ]); 62 | 63 | return new ConversionResult($response['base'], $response['timestamp'], $response['rates']); 64 | } 65 | 66 | /** 67 | * @param int|string|DateTime $date 68 | * @param string|array $forCurrency 69 | * 70 | * @return ConversionResult 71 | * 72 | * @throws CurrencyException 73 | */ 74 | public function historical($date = null, $forCurrency = []): ConversionResult 75 | { 76 | // Set date 77 | $this->date($date); 78 | 79 | if (!empty((array)$forCurrency)) { 80 | $this->currencies((array)$forCurrency); 81 | } 82 | 83 | if (null === $this->getDate()) { 84 | throw new ApiException('Date needs to be set!'); 85 | } 86 | 87 | // Get API response 88 | $response = $this->apiRequest("historical/{$this->getDate()}.json", [ 89 | 'base' => $this->getBaseCurrency(), 90 | 'symbols' => join(',', $this->getSymbols()), 91 | ]); 92 | 93 | return new ConversionResult($response['base'], $response['timestamp'], $response['rates']); 94 | } 95 | 96 | /** 97 | * Converts any amount in a given currency to another currency. 98 | * 99 | * @param float $amount The amount to convert. 100 | * @param string $fromCurrency The base currency. 101 | * @param string $toCurrency The target currency. 102 | * @param int|string|DateTime $date The date to get the conversion rate for. 103 | * 104 | * @return float The conversion result. 105 | * 106 | * @throws ApiException 107 | */ 108 | public function convert(float $amount = null, string $fromCurrency = null, string $toCurrency = null, $date = null): float 109 | { 110 | // Set date 111 | $this->date($date); 112 | 113 | // Overwrite/set params 114 | if ($amount !== null) { 115 | $this->amount = $amount; 116 | } 117 | 118 | if ($fromCurrency !== null) { 119 | $this->baseCurrency = $fromCurrency; 120 | } 121 | 122 | if ($toCurrency !== null) { 123 | $this->currencies = [$toCurrency]; 124 | } 125 | 126 | if (null !== $this->getDate()) { 127 | $params['date'] = $this->getDate(); 128 | } 129 | 130 | $targetCurrency = reset($this->currencies); 131 | 132 | // Get API response 133 | $response = $this->apiRequest("convert/{$this->amount}/{$this->getBaseCurrency()}/{$targetCurrency}"); 134 | 135 | // Return the rate as a float 136 | return floatval($response['response']); 137 | } 138 | 139 | /** 140 | * Performs an HTTP request. 141 | * 142 | * @param string $endpoint The API endpoint. 143 | * @param array $params The query parameters for this request. 144 | * @param string $method The HTTP method (defaults to 'GET'). 145 | * 146 | * @return array|bool The response as decoded JSON. 147 | * 148 | * @throws ApiException 149 | */ 150 | function apiRequest(string $endpoint, array $params = [], string $method = 'GET') 151 | { 152 | // Perform actual API request. 153 | $response = parent::apiRequest($endpoint, $params, $method); 154 | 155 | // Handle response exceptions. 156 | if (isset($response['error']) && $response['error'] == true) { 157 | throw new ApiException("[{$response['message']}] {$response['description']}", $response['status']); 158 | } 159 | 160 | return $response; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/Exceptions/ApiException.php: -------------------------------------------------------------------------------- 1 | format($format); 48 | } else if ($date === 'now') { 49 | return date($format); 50 | } else if (is_string($date)) { 51 | return (new DateTime($date))->format($format); 52 | } else { 53 | $timestamp = (integer)$date; 54 | return date($format, $timestamp); 55 | } 56 | } 57 | 58 | /** 59 | * Get a date object by given date or time format 60 | * 61 | * Examples:: 62 | * 63 | * Date.create('2018-12-04') 64 | * Date.create('first day of next year') 65 | * 66 | * @param String $time A date/time string. For valid formats see http://php.net/manual/en/datetime.formats.php 67 | * 68 | * @return DateTime 69 | * 70 | * @throws Exception 71 | */ 72 | public static function create(string $time): DateTime 73 | { 74 | return new DateTime($time); 75 | } 76 | 77 | /** 78 | * Get the current date and time 79 | * 80 | * Examples:: 81 | * 82 | * Date.now().timestamp 83 | * 84 | * @return DateTime 85 | * 86 | * @throws Exception 87 | */ 88 | public static function now(): DateTime 89 | { 90 | return new DateTime('now'); 91 | } 92 | 93 | /** 94 | * Get the current date 95 | * 96 | * @return DateTime 97 | * 98 | * @throws Exception 99 | */ 100 | public static function today(): DateTime 101 | { 102 | return new DateTime('today'); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/Results/ConversionResult.php: -------------------------------------------------------------------------------- 1 | originalBaseCurrency = $baseCurrency; 35 | $this->baseCurrency = $baseCurrency; 36 | 37 | $this->date = DateHelper::format($date, 'Y-m-d'); 38 | 39 | $rates[$baseCurrency] = 1.0; 40 | 41 | $this->originalConversionRates = $rates; 42 | $this->conversionRates = $rates; 43 | } 44 | 45 | /** 46 | * Get base currency. 47 | * 48 | * @return string 49 | */ 50 | public function getBaseCurrency(): string 51 | { 52 | return $this->baseCurrency; 53 | } 54 | 55 | /** 56 | * Set new base currency. 57 | * 58 | * @param string $baseCurrency The new base currency. 59 | * 60 | * @return self 61 | * 62 | * @throws CurrencyException 63 | */ 64 | public function setBaseCurrency(string $baseCurrency): ConversionResult 65 | { 66 | if (!isset($this->conversionRates[$baseCurrency])) { 67 | throw new CurrencyException("No conversion result for '$baseCurrency'!"); 68 | } 69 | 70 | if ($baseCurrency == $this->originalBaseCurrency) { 71 | $this->conversionRates = $this->originalConversionRates; 72 | return $this; 73 | } 74 | 75 | // Calculate new conversion rates. 76 | foreach ($this->originalConversionRates as $currency => $rate) { 77 | $this->conversionRates[$currency] = (float)$rate / (float)$this->originalConversionRates[$baseCurrency]; 78 | } 79 | 80 | // Set new base currency. 81 | $this->baseCurrency = $baseCurrency; 82 | $this->conversionRates[$baseCurrency] = 1.0; 83 | 84 | // Return self 85 | return $this; 86 | } 87 | 88 | /** 89 | * Get date. 90 | */ 91 | public function getDate() 92 | { 93 | return $this->date; 94 | } 95 | 96 | /** 97 | * @param string $currency 98 | * 99 | * @return float 100 | * 101 | * @throws CurrencyException 102 | */ 103 | public function rate(string $currency): float 104 | { 105 | if (!isset($this->conversionRates[$currency])) { 106 | throw new CurrencyException("No conversion result for $currency!"); 107 | } 108 | 109 | return $this->conversionRates[$currency]; 110 | } 111 | 112 | /** 113 | * @param float $amount 114 | * @param string $fromCurrency 115 | * @param string $toCurrency 116 | * 117 | * @return float 118 | * 119 | * @throws CurrencyException 120 | */ 121 | function convert(float $amount, string $fromCurrency, string $toCurrency): float 122 | { 123 | if (!isset($this->conversionRates[$toCurrency])) { 124 | throw new CurrencyException("No conversion result for '$toCurrency'!"); 125 | } 126 | 127 | if (!isset($this->conversionRates[$fromCurrency])) { 128 | throw new CurrencyException("No conversion result for '$fromCurrency'!"); 129 | } 130 | 131 | return $amount * (float)$this->originalConversionRates[$toCurrency] / (float)$this->originalConversionRates[$fromCurrency]; 132 | } 133 | 134 | /** 135 | * @return array 136 | */ 137 | public function all(): array 138 | { 139 | return $this->conversionRates; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/Symbol.php: -------------------------------------------------------------------------------- 1 | 'United Arab Emirates Dirham', 183 | 'AFN' => 'Afghan Afghani', 184 | 'ALL' => 'Albanian Lek', 185 | 'AMD' => 'Armenian Dram', 186 | 'ANG' => 'Netherlands Antillean Guilder', 187 | 'AOA' => 'Angolan Kwanza', 188 | 'ARS' => 'Argentine Peso', 189 | 'AUD' => 'Australian Dollar', 190 | 'AWG' => 'Aruban Florin', 191 | 'AZN' => 'Azerbaijani Manat', 192 | 'BAM' => 'Bosnia Herzegovina Convertible Mark', 193 | 'BBD' => 'Barbadian Dollar', 194 | 'BDT' => 'Bangladeshi Taka', 195 | 'BGN' => 'Bulgarian Lev', 196 | 'BHD' => 'Bahraini Dinar', 197 | 'BIF' => 'Burundian Franc', 198 | 'BMD' => 'Bermudan Dollar', 199 | 'BND' => 'Brunei Dollar', 200 | 'BOB' => 'Bolivian Boliviano', 201 | 'BRL' => 'Brazilian Real', 202 | 'BSD' => 'Bahamian Dollar', 203 | 'BTC' => 'Bitcoin', 204 | 'BTN' => 'Bhutanese Ngultrum', 205 | 'BWP' => 'Botswanan Pula', 206 | 'BYR' => 'Belarusian Ruble', 207 | 'BYN' => 'New Belarusian Ruble', 208 | 'BZD' => 'Belize Dollar', 209 | 'CAD' => 'Canadian Dollar', 210 | 'CDF' => 'Congolese Franc', 211 | 'CHF' => 'Swiss Franc', 212 | 'CLF' => 'Chilean Unit of Account', 213 | 'CLP' => 'Chilean Peso', 214 | 'CNY' => 'Chinese Yuan', 215 | 'COP' => 'Colombian Peso', 216 | 'CRC' => 'Costa Rican Colón', 217 | 'CUC' => 'Cuban Convertible Peso', 218 | 'CUP' => 'Cuban Peso', 219 | 'CVE' => 'Cape Verdean Escudo', 220 | 'CZK' => 'Czech Republic Koruna', 221 | 'DJF' => 'Djiboutian Franc', 222 | 'DKK' => 'Danish Krone', 223 | 'DOP' => 'Dominican Peso', 224 | 'DZD' => 'Algerian Dinar', 225 | 'EGP' => 'Egyptian Pound', 226 | 'ERN' => 'Eritrean Nakfa', 227 | 'ETB' => 'Ethiopian Birr', 228 | 'EUR' => 'Euro', 229 | 'FJD' => 'Fijian Dollar', 230 | 'FKP' => 'Falkland Islands Pound', 231 | 'GBP' => 'British Pound Sterling', 232 | 'GEL' => 'Georgian Lari', 233 | 'GGP' => 'Guernsey Pound', 234 | 'GHS' => 'Ghanaian Cedi', 235 | 'GIP' => 'Gibraltar Pound', 236 | 'GMD' => 'Gambian Dalasi', 237 | 'GNF' => 'Guinean Franc', 238 | 'GTQ' => 'Guatemalan Quetzal', 239 | 'GYD' => 'Guyanaese Dollar', 240 | 'HKD' => 'Hong Kong Dollar', 241 | 'HNL' => 'Honduran Lempira', 242 | 'HRK' => 'Croatian Kuna', 243 | 'HTG' => 'Haitian Gourde', 244 | 'HUF' => 'Hungarian Forint', 245 | 'IDR' => 'Indonesian Rupiah', 246 | 'ILS' => 'Israeli New Sheqel', 247 | 'IMP' => 'Manx pound', 248 | 'INR' => 'Indian Rupee', 249 | 'IQD' => 'Iraqi Dinar', 250 | 'IRR' => 'Iranian Rial', 251 | 'ISK' => 'Icelandic Króna', 252 | 'JEP' => 'Jersey Pound', 253 | 'JMD' => 'Jamaican Dollar', 254 | 'JOD' => 'Jordanian Dinar', 255 | 'JPY' => 'Japanese Yen', 256 | 'KES' => 'Kenyan Shilling', 257 | 'KGS' => 'Kyrgystani Som', 258 | 'KHR' => 'Cambodian Riel', 259 | 'KMF' => 'Comorian Franc', 260 | 'KPW' => 'North Korean Won', 261 | 'KRW' => 'South Korean Won', 262 | 'KWD' => 'Kuwaiti Dinar', 263 | 'KYD' => 'Cayman Islands Dollar', 264 | 'KZT' => 'Kazakhstani Tenge', 265 | 'LAK' => 'Laotian Kip', 266 | 'LBP' => 'Lebanese Pound', 267 | 'LKR' => 'Sri Lankan Rupee', 268 | 'LRD' => 'Liberian Dollar', 269 | 'LSL' => 'Lesotho Loti', 270 | 'LTL' => 'Lithuanian Litas', 271 | 'LVL' => 'Latvian Lats', 272 | 'LYD' => 'Libyan Dinar', 273 | 'MAD' => 'Moroccan Dirham', 274 | 'MDL' => 'Moldovan Leu', 275 | 'MGA' => 'Malagasy Ariary', 276 | 'MKD' => 'Macedonian Denar', 277 | 'MMK' => 'Myanma Kyat', 278 | 'MNT' => 'Mongolian Tugrik', 279 | 'MOP' => 'Macanese Pataca', 280 | 'MRO' => 'Mauritanian Ouguiya', 281 | 'MUR' => 'Mauritian Rupee', 282 | 'MVR' => 'Maldivian Rufiyaa', 283 | 'MWK' => 'Malawian Kwacha', 284 | 'MXN' => 'Mexican Peso', 285 | 'MYR' => 'Malaysian Ringgit', 286 | 'MZN' => 'Mozambican Metical', 287 | 'NAD' => 'Namibian Dollar', 288 | 'NGN' => 'Nigerian Naira', 289 | 'NIO' => 'Nicaraguan Córdoba', 290 | 'NOK' => 'Norwegian Krone', 291 | 'NPR' => 'Nepalese Rupee', 292 | 'NZD' => 'New Zealand Dollar', 293 | 'OMR' => 'Omani Rial', 294 | 'PAB' => 'Panamanian Balboa', 295 | 'PEN' => 'Peruvian Nuevo Sol', 296 | 'PGK' => 'Papua New Guinean Kina', 297 | 'PHP' => 'Philippine Peso', 298 | 'PKR' => 'Pakistani Rupee', 299 | 'PLN' => 'Polish Zloty', 300 | 'PYG' => 'Paraguayan Guarani', 301 | 'QAR' => 'Qatari Rial', 302 | 'RON' => 'Romanian Leu', 303 | 'RSD' => 'Serbian Dinar', 304 | 'RUB' => 'Russian Ruble', 305 | 'RWF' => 'Rwandan Franc', 306 | 'SAR' => 'Saudi Riyal', 307 | 'SBD' => 'Solomon Islands Dollar', 308 | 'SCR' => 'Seychellois Rupee', 309 | 'SDG' => 'Sudanese Pound', 310 | 'SEK' => 'Swedish Krona', 311 | 'SGD' => 'Singapore Dollar', 312 | 'SHP' => 'Saint Helena Pound', 313 | 'SLL' => 'Sierra Leonean Leone', 314 | 'SOS' => 'Somali Shilling', 315 | 'SRD' => 'Surinamese Dollar', 316 | 'STD' => 'São Tomé and Príncipe Dobra', 317 | 'SVC' => 'Salvadoran Colón', 318 | 'SYP' => 'Syrian Pound', 319 | 'SZL' => 'Swazi Lilangeni', 320 | 'THB' => 'Thai Baht', 321 | 'TJS' => 'Tajikistani Somoni', 322 | 'TMT' => 'Turkmenistani Manat', 323 | 'TND' => 'Tunisian Dinar', 324 | 'TOP' => 'Tongan Paʻanga', 325 | 'TRY' => 'Turkish Lira', 326 | 'TTD' => 'Trinidad and Tobago Dollar', 327 | 'TWD' => 'New Taiwan Dollar', 328 | 'TZS' => 'Tanzanian Shilling', 329 | 'UAH' => 'Ukrainian Hryvnia', 330 | 'UGX' => 'Ugandan Shilling', 331 | 'USD' => 'United States Dollar', 332 | 'UYU' => 'Uruguayan Peso', 333 | 'UZS' => 'Uzbekistan Som', 334 | 'VEF' => 'Venezuelan Bolívar Fuerte', 335 | 'VND' => 'Vietnamese Dong', 336 | 'VUV' => 'Vanuatu Vatu', 337 | 'WST' => 'Samoan Tala', 338 | 'XAF' => 'CFA Franc BEAC', 339 | 'XAG' => 'Silver', 340 | 'XAU' => 'Gold', 341 | 'XCD' => 'East Caribbean Dollar', 342 | 'XDR' => 'Special Drawing Rights', 343 | 'XOF' => 'CFA Franc BCEAO', 344 | 'XPF' => 'CFP Franc', 345 | 'YER' => 'Yemeni Rial', 346 | 'ZAR' => 'South African Rand', 347 | 'ZMW' => 'Zambian Kwacha', 348 | 'ZWL' => 'Zimbabwean Dollar', 349 | ]; 350 | 351 | /** 352 | * @return array 353 | * 354 | * @throws ReflectionException 355 | */ 356 | public static function all(): array 357 | { 358 | return array_values((new ReflectionClass(static::class))->getConstants()); 359 | } 360 | 361 | /** 362 | * Retrieve the name of a currency by its symbol. 363 | * 364 | * @param mixed $currency The currency symbol. 365 | * 366 | * @return string 367 | */ 368 | public static function name(string $currency): string 369 | { 370 | return isset(static::$currencyNames[$currency]) ? static::$currencyNames[$currency] : null; 371 | } 372 | 373 | /** 374 | * Retrieve an array of all currencies with their names. 375 | * 376 | * @return array 377 | */ 378 | public static function names(): array 379 | { 380 | return static::$currencyNames; 381 | } 382 | } 383 | --------------------------------------------------------------------------------