├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── data └── GeoLite2-Country.mmdb ├── examples ├── country.php ├── currency.php ├── ip-cached.php ├── ip-chained.php ├── ip.php └── locale.php ├── img ├── fr.png └── us.png ├── spec └── Locurro │ ├── Converter │ ├── CountrySpec.php │ ├── CurrencySpec.php │ ├── IpAddressSpec.php │ └── LocaleSpec.php │ └── Twig │ └── ExtensionSpec.php └── src └── Locurro ├── Converter ├── ConverterInterface.php ├── Country.php ├── Currency.php ├── IpAddress.php └── Locale.php ├── Exception ├── Exception.php ├── GeolocationException.php ├── InvalidArgumentException.php ├── InvalidCountryException.php └── InvalidLocaleException.php └── Twig └── Extension.php /.gitignore: -------------------------------------------------------------------------------- 1 | cache 2 | vendor 3 | bin/phpspec 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | matrix: 4 | include: 5 | - php: 5.4 6 | - php: 5.5 7 | - php: 5.6 8 | - php: 7.0 9 | - php: hhvm 10 | allow_failures: 11 | - php: 7.0 12 | 13 | before_script: 14 | - composer install --dev 15 | 16 | script: 17 | - php bin/phpspec run -f pretty 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Saša Stamenković 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
7 | symfony upgrade fixer • 8 | twig gettext extractor • 9 | wisdom • 10 | centipede • 11 | permissions handler • 12 | extraload • 13 | gravatar • 14 | locurro • 15 | country list • 16 | transliterator 17 |
18 | 19 | # Locurro [](https://travis-ci.org/umpirsky/locurro) 20 | 21 | :euro: Local currency converter. 22 | 23 | ## Use Case 24 | 25 | Imagine you have an online store, and you are selling products in many different countries. 26 | Some of your buyers might live in country that uses currency other then one you use in your store. 27 | It would be cool to give them estimation of product costs in their domestic currency. 28 | 29 | Here is one example of showing approximate price under the brackets: 30 | 31 |  32 |  33 | 34 | And it automatically detects users default currency based on their IP address for example. 35 | 36 | Pretty cool, huh? :smile: 37 | 38 | ## Basic Usage 39 | 40 | ### Convert based on currency 41 | 42 | ```php 43 | convert( 47 | new Money\Money(100, new Money\Currency('EUR')), 48 | new Money\Currency('RSD') 49 | ); 50 | 51 | ``` 52 | 53 | Full example in [examples/currency.php](https://github.com/umpirsky/locurro/blob/master/examples/currency.php). 54 | 55 | ### Convert based on locale 56 | 57 | ```php 58 | convert( 62 | new Money\Money(100, new Money\Currency('EUR')), 63 | 'sr-Cyrl-RS' 64 | ); 65 | 66 | ``` 67 | 68 | Full example in [examples/locale.php](https://github.com/umpirsky/locurro/blob/master/examples/locale.php). 69 | 70 | ### Convert based on country 71 | 72 | ```php 73 | convert( 77 | new Money\Money(100, new Money\Currency('EUR')), 78 | 'RS' 79 | ); 80 | 81 | ``` 82 | 83 | Full example in [examples/country.php](https://github.com/umpirsky/locurro/blob/master/examples/country.php). 84 | 85 | ### Convert based on IP address 86 | 87 | ```php 88 | convert( 92 | new Money\Money(100, new Money\Currency('EUR')), 93 | '109.92.115.78' 94 | ); 95 | 96 | ``` 97 | 98 | Full example in [examples/ip.php](https://github.com/umpirsky/locurro/blob/master/examples/ip.php). 99 | 100 | ## Advanced Usage 101 | 102 | ### Chaining providers 103 | 104 | Locurro uses [Swap](http://florianv.github.io/swap/) library for exchange rates. 105 | 106 | There are multiple exchange rate providers supported: 107 | 108 | - [European Central Bank](http://www.ecb.europa.eu/home/html/index.en.html) 109 | Supports only EUR as base currency. 110 | - [Google Finance](http://www.google.com/finance) 111 | Supports multiple currencies as base and quote currencies. 112 | - [Open Exchange Rates](https://openexchangerates.org) 113 | Supports only USD as base currency for the free version and multiple ones for the enterprise version. 114 | - [Xignite](https://www.xignite.com) 115 | You must have access to the `XigniteGlobalCurrencies` API. 116 | Supports multiple currencies as base and quote currencies. 117 | - [Yahoo Finance](https://finance.yahoo.com/) 118 | Supports multiple currencies as base and quote currencies. 119 | - [WebserviceX](http://www.webservicex.net/ws/default.aspx) 120 | Supports multiple currencies as base and quote currencies. 121 | - [National Bank of Romania](http://www.bnr.ro) 122 | Supports only RON as base currency. 123 | - `Array` 124 | Retrieves rates from a PHP array. 125 | 126 | You can chain them, see example in [examples/ip-chained.php](https://github.com/umpirsky/locurro/blob/master/examples/ip-chained.php). 127 | 128 | ### Caching 129 | 130 | You can cache exchange rates using Doctrine cache or Illuminate cache. 131 | 132 | Example is available in [examples/ip-cached.php](https://github.com/umpirsky/locurro/blob/master/examples/ip-cached.php). 133 | 134 | ### Twig integration 135 | 136 | There is a Twig extension provded in the source code. 137 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "umpirsky/locurro", 3 | "type": "library", 4 | "description": "Local currency converter.", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Saša Stamenković", 9 | "email": "umpirsky@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.4", 14 | "mathiasverraes/money": "^1.2", 15 | "willdurand/geocoder": "^3.0", 16 | "geoip2/geoip2": "^2.3", 17 | "florianv/swap": "^2.2", 18 | "zf1/zend-locale": "^1.12", 19 | "zf1/zend-currency": "^1.12" 20 | }, 21 | "require-dev": { 22 | "doctrine/cache": "^1.4", 23 | "twig/twig": "^1.21", 24 | "phpspec/phpspec": "^2.2" 25 | }, 26 | "suggest": { 27 | "doctrine/cache": "^1.4", 28 | "twig/twig": "^1.21" 29 | }, 30 | "config": { 31 | "bin-dir": "bin" 32 | }, 33 | "autoload": { 34 | "psr-0": { "Locurro\\": "src/" } 35 | }, 36 | "extra": { 37 | "branch-alias": { 38 | "dev-master": "0.2-dev" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /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#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "694124d6b152525f97e83f69731dd35a", 8 | "packages": [ 9 | { 10 | "name": "egeloen/http-adapter", 11 | "version": "0.8.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/egeloen/ivory-http-adapter.git", 15 | "reference": "9641f11487ec26b24c6bbcee4f267cf62f60b855" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/egeloen/ivory-http-adapter/zipball/9641f11487ec26b24c6bbcee4f267cf62f60b855", 20 | "reference": "9641f11487ec26b24c6bbcee4f267cf62f60b855", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.4.8", 25 | "zendframework/zend-diactoros": "^1.1" 26 | }, 27 | "require-dev": { 28 | "cakephp/cakephp": "^3.0.3", 29 | "ext-curl": "*", 30 | "guzzle/guzzle": "^3.9.4@dev", 31 | "guzzlehttp/guzzle": "^4.1.4|^5.0|^6.0", 32 | "kriswallsmith/buzz": "^0.13", 33 | "nategood/httpful": "^0.2.17", 34 | "phpunit/phpunit": "^4.0", 35 | "phpunit/phpunit-mock-objects": "dev-matcher-verify as 2.3.x-dev", 36 | "psr/log": "^1.0", 37 | "react/dns": "^0.4.1", 38 | "react/http-client": "^0.4", 39 | "satooshi/php-coveralls": "^0.6", 40 | "symfony/event-dispatcher": "^2.0", 41 | "zendframework/zend-http": "^2.3.4", 42 | "zendframework/zendframework1": ">=1.12.9,<=1.12.14|^1.12.16" 43 | }, 44 | "suggest": { 45 | "ext-curl": "Allows you to use the cURL adapter", 46 | "ext-http": "Allows you to use the PECL adapter", 47 | "guzzle/guzzle": "Allows you to use the Guzzle 3 adapter", 48 | "guzzlehttp/guzzle": "Allows you to use the Guzzle 4 adapter", 49 | "kriswallsmith/buzz": "Allows you to use the Buzz adapter", 50 | "nategood/httpful": "Allows you to use the httpful adapter", 51 | "psr/log": "Allows you to use the logger event subscriber", 52 | "symfony/event-dispatcher": "Allows you to use the event lifecycle", 53 | "symfony/stopwatch": "Allows you to use the stopwatch http adapter and event subscriber", 54 | "zendframework/zend-http": "Allows you to use the Zend 2 adapter", 55 | "zendframework/zendframework1": "Allows you to use the Zend 1 adapter" 56 | }, 57 | "type": "library", 58 | "extra": { 59 | "branch-alias": { 60 | "dev-master": "0.8-dev" 61 | } 62 | }, 63 | "autoload": { 64 | "psr-4": { 65 | "Ivory\\HttpAdapter\\": "src/" 66 | } 67 | }, 68 | "notification-url": "https://packagist.org/downloads/", 69 | "license": [ 70 | "MIT" 71 | ], 72 | "authors": [ 73 | { 74 | "name": "Eric GELOEN", 75 | "email": "geloen.eric@gmail.com" 76 | } 77 | ], 78 | "description": "Issue HTTP request for PHP 5.3+.", 79 | "keywords": [ 80 | "http", 81 | "http-adapter", 82 | "http-client", 83 | "psr-7" 84 | ], 85 | "time": "2015-08-12 09:35:40" 86 | }, 87 | { 88 | "name": "florianv/swap", 89 | "version": "v2.2.0", 90 | "source": { 91 | "type": "git", 92 | "url": "https://github.com/florianv/swap.git", 93 | "reference": "766e82859f5ee2873a5ebb60e9761c6e3ee7d321" 94 | }, 95 | "dist": { 96 | "type": "zip", 97 | "url": "https://api.github.com/repos/florianv/swap/zipball/766e82859f5ee2873a5ebb60e9761c6e3ee7d321", 98 | "reference": "766e82859f5ee2873a5ebb60e9761c6e3ee7d321", 99 | "shasum": "" 100 | }, 101 | "require": { 102 | "egeloen/http-adapter": "~0.1", 103 | "php": ">=5.4.0" 104 | }, 105 | "require-dev": { 106 | "doctrine/cache": "~1.0", 107 | "illuminate/cache": "~5.0", 108 | "phpunit/phpunit": "~4.0" 109 | }, 110 | "suggest": { 111 | "doctrine/cache": "Required to cache rates with Doctrine cache", 112 | "illuminate/cache": "Required to cache rates with Illuminate cache" 113 | }, 114 | "type": "library", 115 | "extra": { 116 | "branch-alias": { 117 | "dev-master": "2.0-dev" 118 | } 119 | }, 120 | "autoload": { 121 | "psr-4": { 122 | "Swap\\": "src/" 123 | } 124 | }, 125 | "notification-url": "https://packagist.org/downloads/", 126 | "license": [ 127 | "MIT" 128 | ], 129 | "authors": [ 130 | { 131 | "name": "Florian Voutzinos", 132 | "email": "florian@voutzinos.com", 133 | "homepage": "http://florian.voutzinos.com" 134 | } 135 | ], 136 | "description": "Exchange rates library for PHP", 137 | "homepage": "https://github.com/florianv/swap", 138 | "keywords": [ 139 | "Rate", 140 | "conversion", 141 | "currency", 142 | "exchange rates", 143 | "money" 144 | ], 145 | "time": "2015-07-23 18:54:39" 146 | }, 147 | { 148 | "name": "geoip2/geoip2", 149 | "version": "v2.3.1", 150 | "source": { 151 | "type": "git", 152 | "url": "https://github.com/maxmind/GeoIP2-php.git", 153 | "reference": "8bd919d9d829a1f25e01895cdead97c5247aacb7" 154 | }, 155 | "dist": { 156 | "type": "zip", 157 | "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/8bd919d9d829a1f25e01895cdead97c5247aacb7", 158 | "reference": "8bd919d9d829a1f25e01895cdead97c5247aacb7", 159 | "shasum": "" 160 | }, 161 | "require": { 162 | "maxmind-db/reader": "~1.0", 163 | "maxmind/web-service-common": "~0.0.3", 164 | "php": ">=5.3.1" 165 | }, 166 | "require-dev": { 167 | "phpunit/phpunit": "4.2.*" 168 | }, 169 | "type": "library", 170 | "autoload": { 171 | "psr-4": { 172 | "GeoIp2\\": "src", 173 | "": "compat/" 174 | } 175 | }, 176 | "notification-url": "https://packagist.org/downloads/", 177 | "license": [ 178 | "Apache-2.0" 179 | ], 180 | "authors": [ 181 | { 182 | "name": "Gregory J. Oschwald", 183 | "email": "goschwald@maxmind.com", 184 | "homepage": "http://www.maxmind.com/" 185 | } 186 | ], 187 | "description": "MaxMind GeoIP2 PHP API", 188 | "homepage": "https://github.com/maxmind/GeoIP2-php", 189 | "keywords": [ 190 | "IP", 191 | "geoip", 192 | "geoip2", 193 | "geolocation", 194 | "maxmind" 195 | ], 196 | "time": "2015-06-30 19:03:29" 197 | }, 198 | { 199 | "name": "igorw/get-in", 200 | "version": "v1.0.3", 201 | "source": { 202 | "type": "git", 203 | "url": "https://github.com/igorw/get-in.git", 204 | "reference": "170ded831f49abc6a6061f655aba9bdbcf7b8111" 205 | }, 206 | "dist": { 207 | "type": "zip", 208 | "url": "https://api.github.com/repos/igorw/get-in/zipball/170ded831f49abc6a6061f655aba9bdbcf7b8111", 209 | "reference": "170ded831f49abc6a6061f655aba9bdbcf7b8111", 210 | "shasum": "" 211 | }, 212 | "require": { 213 | "php": ">=5.4" 214 | }, 215 | "type": "library", 216 | "extra": { 217 | "branch-alias": { 218 | "dev-master": "1.0-dev" 219 | } 220 | }, 221 | "autoload": { 222 | "files": [ 223 | "src/get_in.php" 224 | ] 225 | }, 226 | "notification-url": "https://packagist.org/downloads/", 227 | "license": [ 228 | "MIT" 229 | ], 230 | "authors": [ 231 | { 232 | "name": "Igor Wiedler", 233 | "email": "igor@wiedler.ch" 234 | } 235 | ], 236 | "description": "Functions for for hash map (assoc array) traversal.", 237 | "keywords": [ 238 | "assoc-array", 239 | "hash-map" 240 | ], 241 | "time": "2014-12-15 23:03:51" 242 | }, 243 | { 244 | "name": "mathiasverraes/money", 245 | "version": "1.2.1", 246 | "source": { 247 | "type": "git", 248 | "url": "https://github.com/mathiasverraes/money.git", 249 | "reference": "b9e258119041fed20e4704f72e3ebb94ed10bea2" 250 | }, 251 | "dist": { 252 | "type": "zip", 253 | "url": "https://api.github.com/repos/mathiasverraes/money/zipball/b9e258119041fed20e4704f72e3ebb94ed10bea2", 254 | "reference": "b9e258119041fed20e4704f72e3ebb94ed10bea2", 255 | "shasum": "" 256 | }, 257 | "require": { 258 | "php": ">=5.3.3" 259 | }, 260 | "require-dev": { 261 | "phpunit/phpunit": "3.7.*" 262 | }, 263 | "suggest": { 264 | "Sylius/SyliusMoneyBundle": "Sylius' Symfony2 integration with Money library", 265 | "TheBigBrainsCompany/TbbcMoneyBundle": "Very complete Symfony2 bundle with support for Twig, Doctrine, Forms, ...", 266 | "pink-tie/money-bundle": "Pink-Tie's Symfony2 integration with Money library" 267 | }, 268 | "type": "library", 269 | "extra": { 270 | "branch-alias": { 271 | "dev-master": "1.3.x-dev" 272 | } 273 | }, 274 | "autoload": { 275 | "psr-0": { 276 | "Money": "lib" 277 | } 278 | }, 279 | "notification-url": "https://packagist.org/downloads/", 280 | "license": [ 281 | "MIT" 282 | ], 283 | "authors": [ 284 | { 285 | "name": "Mathias Verraes", 286 | "email": "mathias@verraes.net" 287 | } 288 | ], 289 | "description": "PHP implementation of Fowler's Money pattern", 290 | "homepage": "http://verraes.net/2011/04/fowler-money-pattern-in-php/", 291 | "keywords": [ 292 | "Generic Sub-domain", 293 | "Value Object", 294 | "money" 295 | ], 296 | "time": "2014-10-07 12:54:10" 297 | }, 298 | { 299 | "name": "maxmind-db/reader", 300 | "version": "v1.0.3", 301 | "source": { 302 | "type": "git", 303 | "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", 304 | "reference": "07f211ab596ba60f9663d9984b888f76ee1beac9" 305 | }, 306 | "dist": { 307 | "type": "zip", 308 | "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/07f211ab596ba60f9663d9984b888f76ee1beac9", 309 | "reference": "07f211ab596ba60f9663d9984b888f76ee1beac9", 310 | "shasum": "" 311 | }, 312 | "require": { 313 | "php": ">=5.3.1" 314 | }, 315 | "require-dev": { 316 | "phpunit/phpunit": "4.2.*", 317 | "satooshi/php-coveralls": "dev-master" 318 | }, 319 | "type": "library", 320 | "autoload": { 321 | "psr-0": { 322 | "MaxMind": "src/" 323 | } 324 | }, 325 | "notification-url": "https://packagist.org/downloads/", 326 | "license": [ 327 | "Apache-2.0" 328 | ], 329 | "authors": [ 330 | { 331 | "name": "Gregory J. Oschwald", 332 | "email": "goschwald@maxmind.com", 333 | "homepage": "http://www.maxmind.com/" 334 | } 335 | ], 336 | "description": "MaxMind DB Reader API", 337 | "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php", 338 | "keywords": [ 339 | "database", 340 | "geoip", 341 | "geoip2", 342 | "geolocation", 343 | "maxmind" 344 | ], 345 | "time": "2015-03-13 22:35:13" 346 | }, 347 | { 348 | "name": "maxmind/web-service-common", 349 | "version": "v0.0.4", 350 | "source": { 351 | "type": "git", 352 | "url": "https://github.com/maxmind/web-service-common-php.git", 353 | "reference": "f26fce5281290973beeeca3e33847887177dd138" 354 | }, 355 | "dist": { 356 | "type": "zip", 357 | "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/f26fce5281290973beeeca3e33847887177dd138", 358 | "reference": "f26fce5281290973beeeca3e33847887177dd138", 359 | "shasum": "" 360 | }, 361 | "require": { 362 | "ext-curl": "*", 363 | "ext-json": "*", 364 | "php": ">=5.3" 365 | }, 366 | "require-dev": { 367 | "phpunit/phpunit": "4.6.*" 368 | }, 369 | "type": "library", 370 | "autoload": { 371 | "psr-4": { 372 | "MaxMind\\": "src" 373 | } 374 | }, 375 | "notification-url": "https://packagist.org/downloads/", 376 | "license": [ 377 | "Apache-2.0" 378 | ], 379 | "authors": [ 380 | { 381 | "name": "Gregory Oschwald", 382 | "email": "goschwald@maxmind.com" 383 | } 384 | ], 385 | "description": "Internal MaxMind Web Service API", 386 | "homepage": "https://github.com/maxmind/mm-web-service-api-php", 387 | "time": "2015-07-21 20:07:31" 388 | }, 389 | { 390 | "name": "psr/http-message", 391 | "version": "1.0", 392 | "source": { 393 | "type": "git", 394 | "url": "https://github.com/php-fig/http-message.git", 395 | "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" 396 | }, 397 | "dist": { 398 | "type": "zip", 399 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", 400 | "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", 401 | "shasum": "" 402 | }, 403 | "require": { 404 | "php": ">=5.3.0" 405 | }, 406 | "type": "library", 407 | "extra": { 408 | "branch-alias": { 409 | "dev-master": "1.0.x-dev" 410 | } 411 | }, 412 | "autoload": { 413 | "psr-4": { 414 | "Psr\\Http\\Message\\": "src/" 415 | } 416 | }, 417 | "notification-url": "https://packagist.org/downloads/", 418 | "license": [ 419 | "MIT" 420 | ], 421 | "authors": [ 422 | { 423 | "name": "PHP-FIG", 424 | "homepage": "http://www.php-fig.org/" 425 | } 426 | ], 427 | "description": "Common interface for HTTP messages", 428 | "keywords": [ 429 | "http", 430 | "http-message", 431 | "psr", 432 | "psr-7", 433 | "request", 434 | "response" 435 | ], 436 | "time": "2015-05-04 20:22:00" 437 | }, 438 | { 439 | "name": "willdurand/geocoder", 440 | "version": "v3.1.0", 441 | "source": { 442 | "type": "git", 443 | "url": "https://github.com/geocoder-php/Geocoder.git", 444 | "reference": "6f446e5bc3de245d83ed3c8c1702afe9318d46f4" 445 | }, 446 | "dist": { 447 | "type": "zip", 448 | "url": "https://api.github.com/repos/geocoder-php/Geocoder/zipball/6f446e5bc3de245d83ed3c8c1702afe9318d46f4", 449 | "reference": "6f446e5bc3de245d83ed3c8c1702afe9318d46f4", 450 | "shasum": "" 451 | }, 452 | "require": { 453 | "egeloen/http-adapter": "~0.8", 454 | "igorw/get-in": "~1.0", 455 | "php": ">=5.4.0" 456 | }, 457 | "require-dev": { 458 | "geoip2/geoip2": "~2.0", 459 | "symfony/stopwatch": "~2.5" 460 | }, 461 | "suggest": { 462 | "ext-geoip": "Enabling the geoip extension allows you to use the MaxMindProvider.", 463 | "geoip/geoip": "If you are going to use the MaxMindBinaryProvider (conflict with geoip extension).", 464 | "geoip2/geoip2": "If you are going to use the GeoIP2DatabaseProvider.", 465 | "symfony/stopwatch": "If you want to use the TimedGeocoder" 466 | }, 467 | "type": "library", 468 | "extra": { 469 | "branch-alias": { 470 | "dev-master": "3.1-dev" 471 | } 472 | }, 473 | "autoload": { 474 | "psr-0": { 475 | "Geocoder": "src/" 476 | } 477 | }, 478 | "notification-url": "https://packagist.org/downloads/", 479 | "license": [ 480 | "MIT" 481 | ], 482 | "authors": [ 483 | { 484 | "name": "William Durand", 485 | "email": "william.durand1@gmail.com" 486 | } 487 | ], 488 | "description": "The almost missing Geocoder PHP 5.4 library.", 489 | "homepage": "http://geocoder-php.org", 490 | "keywords": [ 491 | "abstraction", 492 | "geocoder", 493 | "geocoding", 494 | "geoip" 495 | ], 496 | "time": "2015-08-13 07:42:18" 497 | }, 498 | { 499 | "name": "zendframework/zend-diactoros", 500 | "version": "1.1.3", 501 | "source": { 502 | "type": "git", 503 | "url": "https://github.com/zendframework/zend-diactoros.git", 504 | "reference": "e2f5c12916c74da384058d0dfbc7fbc0b03d1181" 505 | }, 506 | "dist": { 507 | "type": "zip", 508 | "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/e2f5c12916c74da384058d0dfbc7fbc0b03d1181", 509 | "reference": "e2f5c12916c74da384058d0dfbc7fbc0b03d1181", 510 | "shasum": "" 511 | }, 512 | "require": { 513 | "php": ">=5.4", 514 | "psr/http-message": "~1.0" 515 | }, 516 | "provide": { 517 | "psr/http-message-implementation": "~1.0.0" 518 | }, 519 | "require-dev": { 520 | "phpunit/phpunit": "~4.6", 521 | "squizlabs/php_codesniffer": "^2.3.1" 522 | }, 523 | "type": "library", 524 | "extra": { 525 | "branch-alias": { 526 | "dev-master": "1.0-dev", 527 | "dev-develop": "1.1-dev" 528 | } 529 | }, 530 | "autoload": { 531 | "psr-4": { 532 | "Zend\\Diactoros\\": "src/" 533 | } 534 | }, 535 | "notification-url": "https://packagist.org/downloads/", 536 | "license": [ 537 | "BSD-2-Clause" 538 | ], 539 | "description": "PSR HTTP Message implementations", 540 | "homepage": "https://github.com/zendframework/zend-diactoros", 541 | "keywords": [ 542 | "http", 543 | "psr", 544 | "psr-7" 545 | ], 546 | "time": "2015-08-10 20:04:20" 547 | }, 548 | { 549 | "name": "zf1/zend-cache", 550 | "version": "1.12.11", 551 | "source": { 552 | "type": "git", 553 | "url": "https://github.com/zf1/zend-cache.git", 554 | "reference": "c3a6fc20f5d5c5ab7adc16f29f33eb5b2e00d86e" 555 | }, 556 | "dist": { 557 | "type": "zip", 558 | "url": "https://api.github.com/repos/zf1/zend-cache/zipball/c3a6fc20f5d5c5ab7adc16f29f33eb5b2e00d86e", 559 | "reference": "c3a6fc20f5d5c5ab7adc16f29f33eb5b2e00d86e", 560 | "shasum": "" 561 | }, 562 | "require": { 563 | "php": ">=5.2.11", 564 | "zf1/zend-exception": "self.version" 565 | }, 566 | "suggest": { 567 | "zf1/zend-log": "Used in special situations or with special adapters" 568 | }, 569 | "type": "library", 570 | "autoload": { 571 | "psr-0": { 572 | "Zend_Cache": "library/" 573 | } 574 | }, 575 | "notification-url": "https://packagist.org/downloads/", 576 | "license": [ 577 | "BSD-3-Clause" 578 | ], 579 | "description": "Zend Framework 1 Cache package", 580 | "homepage": "http://framework.zend.com/", 581 | "keywords": [ 582 | "ZF1", 583 | "cache", 584 | "framework", 585 | "zend" 586 | ], 587 | "time": "2015-04-30 11:07:42" 588 | }, 589 | { 590 | "name": "zf1/zend-currency", 591 | "version": "1.12.11", 592 | "source": { 593 | "type": "git", 594 | "url": "https://github.com/zf1/zend-currency.git", 595 | "reference": "da0d1449653b705b5c86ab1a2763d9abb88e33f5" 596 | }, 597 | "dist": { 598 | "type": "zip", 599 | "url": "https://api.github.com/repos/zf1/zend-currency/zipball/da0d1449653b705b5c86ab1a2763d9abb88e33f5", 600 | "reference": "da0d1449653b705b5c86ab1a2763d9abb88e33f5", 601 | "shasum": "" 602 | }, 603 | "require": { 604 | "php": ">=5.2.11", 605 | "zf1/zend-exception": "self.version", 606 | "zf1/zend-locale": "self.version" 607 | }, 608 | "type": "library", 609 | "autoload": { 610 | "psr-0": { 611 | "Zend_Currency": "library/" 612 | } 613 | }, 614 | "notification-url": "https://packagist.org/downloads/", 615 | "license": [ 616 | "BSD-3-Clause" 617 | ], 618 | "description": "Zend Framework 1 Currency package", 619 | "homepage": "http://framework.zend.com/", 620 | "keywords": [ 621 | "ZF1", 622 | "currency", 623 | "framework", 624 | "zend" 625 | ], 626 | "time": "2015-04-30 11:08:48" 627 | }, 628 | { 629 | "name": "zf1/zend-exception", 630 | "version": "1.12.11", 631 | "source": { 632 | "type": "git", 633 | "url": "https://github.com/zf1/zend-exception.git", 634 | "reference": "ca30959d3e2f522f481a3d1459386acf1aa4ca74" 635 | }, 636 | "dist": { 637 | "type": "zip", 638 | "url": "https://api.github.com/repos/zf1/zend-exception/zipball/ca30959d3e2f522f481a3d1459386acf1aa4ca74", 639 | "reference": "ca30959d3e2f522f481a3d1459386acf1aa4ca74", 640 | "shasum": "" 641 | }, 642 | "require": { 643 | "php": ">=5.2.11" 644 | }, 645 | "type": "library", 646 | "autoload": { 647 | "psr-0": { 648 | "Zend_Exception": "library/" 649 | } 650 | }, 651 | "notification-url": "https://packagist.org/downloads/", 652 | "license": [ 653 | "BSD-3-Clause" 654 | ], 655 | "description": "Zend Framework 1 Exception package", 656 | "homepage": "http://framework.zend.com/", 657 | "keywords": [ 658 | "ZF1", 659 | "exception", 660 | "framework", 661 | "zend" 662 | ], 663 | "time": "2015-04-30 11:10:20" 664 | }, 665 | { 666 | "name": "zf1/zend-locale", 667 | "version": "1.12.11", 668 | "source": { 669 | "type": "git", 670 | "url": "https://github.com/zf1/zend-locale.git", 671 | "reference": "370ec210a082221d83edf6d057371f0393733c8f" 672 | }, 673 | "dist": { 674 | "type": "zip", 675 | "url": "https://api.github.com/repos/zf1/zend-locale/zipball/370ec210a082221d83edf6d057371f0393733c8f", 676 | "reference": "370ec210a082221d83edf6d057371f0393733c8f", 677 | "shasum": "" 678 | }, 679 | "require": { 680 | "php": ">=5.2.11", 681 | "zf1/zend-cache": "self.version", 682 | "zf1/zend-exception": "self.version", 683 | "zf1/zend-xml": "self.version" 684 | }, 685 | "suggest": { 686 | "zf1/zend-registry": "Used in special situations or with special adapters" 687 | }, 688 | "type": "library", 689 | "autoload": { 690 | "psr-0": { 691 | "Zend_Locale": "library/" 692 | } 693 | }, 694 | "notification-url": "https://packagist.org/downloads/", 695 | "license": [ 696 | "BSD-3-Clause" 697 | ], 698 | "description": "Zend Framework 1 Locale package", 699 | "homepage": "http://framework.zend.com/", 700 | "keywords": [ 701 | "ZF1", 702 | "framework", 703 | "locale", 704 | "zend" 705 | ], 706 | "time": "2015-04-30 11:10:41" 707 | }, 708 | { 709 | "name": "zf1/zend-xml", 710 | "version": "1.12.11", 711 | "source": { 712 | "type": "git", 713 | "url": "https://github.com/zf1/zend-xml.git", 714 | "reference": "330ca342f69ad446b874158acc9b90dc43d9bbaa" 715 | }, 716 | "dist": { 717 | "type": "zip", 718 | "url": "https://api.github.com/repos/zf1/zend-xml/zipball/330ca342f69ad446b874158acc9b90dc43d9bbaa", 719 | "reference": "330ca342f69ad446b874158acc9b90dc43d9bbaa", 720 | "shasum": "" 721 | }, 722 | "require": { 723 | "php": ">=5.2.11", 724 | "zf1/zend-exception": "self.version" 725 | }, 726 | "type": "library", 727 | "autoload": { 728 | "psr-0": { 729 | "Zend_Xml": "library/" 730 | } 731 | }, 732 | "notification-url": "https://packagist.org/downloads/", 733 | "license": [ 734 | "BSD-3-Clause" 735 | ], 736 | "description": "Zend Framework 1 Xml package", 737 | "homepage": "http://framework.zend.com/", 738 | "keywords": [ 739 | "ZF1", 740 | "framework", 741 | "xml", 742 | "zend" 743 | ], 744 | "time": "2015-04-30 11:12:33" 745 | } 746 | ], 747 | "packages-dev": [ 748 | { 749 | "name": "doctrine/cache", 750 | "version": "v1.4.2", 751 | "source": { 752 | "type": "git", 753 | "url": "https://github.com/doctrine/cache.git", 754 | "reference": "8c434000f420ade76a07c64cbe08ca47e5c101ca" 755 | }, 756 | "dist": { 757 | "type": "zip", 758 | "url": "https://api.github.com/repos/doctrine/cache/zipball/8c434000f420ade76a07c64cbe08ca47e5c101ca", 759 | "reference": "8c434000f420ade76a07c64cbe08ca47e5c101ca", 760 | "shasum": "" 761 | }, 762 | "require": { 763 | "php": ">=5.3.2" 764 | }, 765 | "conflict": { 766 | "doctrine/common": ">2.2,<2.4" 767 | }, 768 | "require-dev": { 769 | "phpunit/phpunit": ">=3.7", 770 | "predis/predis": "~1.0", 771 | "satooshi/php-coveralls": "~0.6" 772 | }, 773 | "type": "library", 774 | "extra": { 775 | "branch-alias": { 776 | "dev-master": "1.5.x-dev" 777 | } 778 | }, 779 | "autoload": { 780 | "psr-0": { 781 | "Doctrine\\Common\\Cache\\": "lib/" 782 | } 783 | }, 784 | "notification-url": "https://packagist.org/downloads/", 785 | "license": [ 786 | "MIT" 787 | ], 788 | "authors": [ 789 | { 790 | "name": "Roman Borschel", 791 | "email": "roman@code-factory.org" 792 | }, 793 | { 794 | "name": "Benjamin Eberlei", 795 | "email": "kontakt@beberlei.de" 796 | }, 797 | { 798 | "name": "Guilherme Blanco", 799 | "email": "guilhermeblanco@gmail.com" 800 | }, 801 | { 802 | "name": "Jonathan Wage", 803 | "email": "jonwage@gmail.com" 804 | }, 805 | { 806 | "name": "Johannes Schmitt", 807 | "email": "schmittjoh@gmail.com" 808 | } 809 | ], 810 | "description": "Caching library offering an object-oriented API for many cache backends", 811 | "homepage": "http://www.doctrine-project.org", 812 | "keywords": [ 813 | "cache", 814 | "caching" 815 | ], 816 | "time": "2015-08-31 12:36:41" 817 | }, 818 | { 819 | "name": "doctrine/instantiator", 820 | "version": "1.0.5", 821 | "source": { 822 | "type": "git", 823 | "url": "https://github.com/doctrine/instantiator.git", 824 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 825 | }, 826 | "dist": { 827 | "type": "zip", 828 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 829 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 830 | "shasum": "" 831 | }, 832 | "require": { 833 | "php": ">=5.3,<8.0-DEV" 834 | }, 835 | "require-dev": { 836 | "athletic/athletic": "~0.1.8", 837 | "ext-pdo": "*", 838 | "ext-phar": "*", 839 | "phpunit/phpunit": "~4.0", 840 | "squizlabs/php_codesniffer": "~2.0" 841 | }, 842 | "type": "library", 843 | "extra": { 844 | "branch-alias": { 845 | "dev-master": "1.0.x-dev" 846 | } 847 | }, 848 | "autoload": { 849 | "psr-4": { 850 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 851 | } 852 | }, 853 | "notification-url": "https://packagist.org/downloads/", 854 | "license": [ 855 | "MIT" 856 | ], 857 | "authors": [ 858 | { 859 | "name": "Marco Pivetta", 860 | "email": "ocramius@gmail.com", 861 | "homepage": "http://ocramius.github.com/" 862 | } 863 | ], 864 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 865 | "homepage": "https://github.com/doctrine/instantiator", 866 | "keywords": [ 867 | "constructor", 868 | "instantiate" 869 | ], 870 | "time": "2015-06-14 21:17:01" 871 | }, 872 | { 873 | "name": "phpdocumentor/reflection-docblock", 874 | "version": "2.0.4", 875 | "source": { 876 | "type": "git", 877 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 878 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" 879 | }, 880 | "dist": { 881 | "type": "zip", 882 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", 883 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", 884 | "shasum": "" 885 | }, 886 | "require": { 887 | "php": ">=5.3.3" 888 | }, 889 | "require-dev": { 890 | "phpunit/phpunit": "~4.0" 891 | }, 892 | "suggest": { 893 | "dflydev/markdown": "~1.0", 894 | "erusev/parsedown": "~1.0" 895 | }, 896 | "type": "library", 897 | "extra": { 898 | "branch-alias": { 899 | "dev-master": "2.0.x-dev" 900 | } 901 | }, 902 | "autoload": { 903 | "psr-0": { 904 | "phpDocumentor": [ 905 | "src/" 906 | ] 907 | } 908 | }, 909 | "notification-url": "https://packagist.org/downloads/", 910 | "license": [ 911 | "MIT" 912 | ], 913 | "authors": [ 914 | { 915 | "name": "Mike van Riel", 916 | "email": "mike.vanriel@naenius.com" 917 | } 918 | ], 919 | "time": "2015-02-03 12:10:50" 920 | }, 921 | { 922 | "name": "phpspec/php-diff", 923 | "version": "v1.0.2", 924 | "source": { 925 | "type": "git", 926 | "url": "https://github.com/phpspec/php-diff.git", 927 | "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a" 928 | }, 929 | "dist": { 930 | "type": "zip", 931 | "url": "https://api.github.com/repos/phpspec/php-diff/zipball/30e103d19519fe678ae64a60d77884ef3d71b28a", 932 | "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a", 933 | "shasum": "" 934 | }, 935 | "type": "library", 936 | "autoload": { 937 | "psr-0": { 938 | "Diff": "lib/" 939 | } 940 | }, 941 | "notification-url": "https://packagist.org/downloads/", 942 | "license": [ 943 | "BSD-3-Clause" 944 | ], 945 | "authors": [ 946 | { 947 | "name": "Chris Boulton", 948 | "homepage": "http://github.com/chrisboulton", 949 | "role": "Original developer" 950 | } 951 | ], 952 | "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", 953 | "time": "2013-11-01 13:02:21" 954 | }, 955 | { 956 | "name": "phpspec/phpspec", 957 | "version": "2.2.1", 958 | "source": { 959 | "type": "git", 960 | "url": "https://github.com/phpspec/phpspec.git", 961 | "reference": "e9a40577323e67f1de2e214abf32976a0352d8f8" 962 | }, 963 | "dist": { 964 | "type": "zip", 965 | "url": "https://api.github.com/repos/phpspec/phpspec/zipball/e9a40577323e67f1de2e214abf32976a0352d8f8", 966 | "reference": "e9a40577323e67f1de2e214abf32976a0352d8f8", 967 | "shasum": "" 968 | }, 969 | "require": { 970 | "doctrine/instantiator": "^1.0.1", 971 | "php": ">=5.3.3", 972 | "phpspec/php-diff": "~1.0.0", 973 | "phpspec/prophecy": "~1.4", 974 | "sebastian/exporter": "~1.0", 975 | "symfony/console": "~2.3", 976 | "symfony/event-dispatcher": "~2.1", 977 | "symfony/finder": "~2.1", 978 | "symfony/process": "~2.1", 979 | "symfony/yaml": "~2.1" 980 | }, 981 | "require-dev": { 982 | "behat/behat": "^3.0.11", 983 | "bossa/phpspec2-expect": "~1.0", 984 | "phpunit/phpunit": "~4.4", 985 | "symfony/filesystem": "~2.1", 986 | "symfony/process": "~2.1" 987 | }, 988 | "suggest": { 989 | "phpspec/nyan-formatters": "~1.0 – Adds Nyan formatters" 990 | }, 991 | "bin": [ 992 | "bin/phpspec" 993 | ], 994 | "type": "library", 995 | "extra": { 996 | "branch-alias": { 997 | "dev-master": "2.2.x-dev" 998 | } 999 | }, 1000 | "autoload": { 1001 | "psr-0": { 1002 | "PhpSpec": "src/" 1003 | } 1004 | }, 1005 | "notification-url": "https://packagist.org/downloads/", 1006 | "license": [ 1007 | "MIT" 1008 | ], 1009 | "authors": [ 1010 | { 1011 | "name": "Konstantin Kudryashov", 1012 | "email": "ever.zet@gmail.com", 1013 | "homepage": "http://everzet.com" 1014 | }, 1015 | { 1016 | "name": "Marcello Duarte", 1017 | "homepage": "http://marcelloduarte.net/" 1018 | } 1019 | ], 1020 | "description": "Specification-oriented BDD framework for PHP 5.3+", 1021 | "homepage": "http://phpspec.net/", 1022 | "keywords": [ 1023 | "BDD", 1024 | "SpecBDD", 1025 | "TDD", 1026 | "spec", 1027 | "specification", 1028 | "testing", 1029 | "tests" 1030 | ], 1031 | "time": "2015-05-30 15:21:40" 1032 | }, 1033 | { 1034 | "name": "phpspec/prophecy", 1035 | "version": "v1.5.0", 1036 | "source": { 1037 | "type": "git", 1038 | "url": "https://github.com/phpspec/prophecy.git", 1039 | "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7" 1040 | }, 1041 | "dist": { 1042 | "type": "zip", 1043 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7", 1044 | "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7", 1045 | "shasum": "" 1046 | }, 1047 | "require": { 1048 | "doctrine/instantiator": "^1.0.2", 1049 | "phpdocumentor/reflection-docblock": "~2.0", 1050 | "sebastian/comparator": "~1.1" 1051 | }, 1052 | "require-dev": { 1053 | "phpspec/phpspec": "~2.0" 1054 | }, 1055 | "type": "library", 1056 | "extra": { 1057 | "branch-alias": { 1058 | "dev-master": "1.4.x-dev" 1059 | } 1060 | }, 1061 | "autoload": { 1062 | "psr-0": { 1063 | "Prophecy\\": "src/" 1064 | } 1065 | }, 1066 | "notification-url": "https://packagist.org/downloads/", 1067 | "license": [ 1068 | "MIT" 1069 | ], 1070 | "authors": [ 1071 | { 1072 | "name": "Konstantin Kudryashov", 1073 | "email": "ever.zet@gmail.com", 1074 | "homepage": "http://everzet.com" 1075 | }, 1076 | { 1077 | "name": "Marcello Duarte", 1078 | "email": "marcello.duarte@gmail.com" 1079 | } 1080 | ], 1081 | "description": "Highly opinionated mocking framework for PHP 5.3+", 1082 | "homepage": "https://github.com/phpspec/prophecy", 1083 | "keywords": [ 1084 | "Double", 1085 | "Dummy", 1086 | "fake", 1087 | "mock", 1088 | "spy", 1089 | "stub" 1090 | ], 1091 | "time": "2015-08-13 10:07:40" 1092 | }, 1093 | { 1094 | "name": "sebastian/comparator", 1095 | "version": "1.2.0", 1096 | "source": { 1097 | "type": "git", 1098 | "url": "https://github.com/sebastianbergmann/comparator.git", 1099 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" 1100 | }, 1101 | "dist": { 1102 | "type": "zip", 1103 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", 1104 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", 1105 | "shasum": "" 1106 | }, 1107 | "require": { 1108 | "php": ">=5.3.3", 1109 | "sebastian/diff": "~1.2", 1110 | "sebastian/exporter": "~1.2" 1111 | }, 1112 | "require-dev": { 1113 | "phpunit/phpunit": "~4.4" 1114 | }, 1115 | "type": "library", 1116 | "extra": { 1117 | "branch-alias": { 1118 | "dev-master": "1.2.x-dev" 1119 | } 1120 | }, 1121 | "autoload": { 1122 | "classmap": [ 1123 | "src/" 1124 | ] 1125 | }, 1126 | "notification-url": "https://packagist.org/downloads/", 1127 | "license": [ 1128 | "BSD-3-Clause" 1129 | ], 1130 | "authors": [ 1131 | { 1132 | "name": "Jeff Welch", 1133 | "email": "whatthejeff@gmail.com" 1134 | }, 1135 | { 1136 | "name": "Volker Dusch", 1137 | "email": "github@wallbash.com" 1138 | }, 1139 | { 1140 | "name": "Bernhard Schussek", 1141 | "email": "bschussek@2bepublished.at" 1142 | }, 1143 | { 1144 | "name": "Sebastian Bergmann", 1145 | "email": "sebastian@phpunit.de" 1146 | } 1147 | ], 1148 | "description": "Provides the functionality to compare PHP values for equality", 1149 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 1150 | "keywords": [ 1151 | "comparator", 1152 | "compare", 1153 | "equality" 1154 | ], 1155 | "time": "2015-07-26 15:48:44" 1156 | }, 1157 | { 1158 | "name": "sebastian/diff", 1159 | "version": "1.3.0", 1160 | "source": { 1161 | "type": "git", 1162 | "url": "https://github.com/sebastianbergmann/diff.git", 1163 | "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" 1164 | }, 1165 | "dist": { 1166 | "type": "zip", 1167 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", 1168 | "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", 1169 | "shasum": "" 1170 | }, 1171 | "require": { 1172 | "php": ">=5.3.3" 1173 | }, 1174 | "require-dev": { 1175 | "phpunit/phpunit": "~4.2" 1176 | }, 1177 | "type": "library", 1178 | "extra": { 1179 | "branch-alias": { 1180 | "dev-master": "1.3-dev" 1181 | } 1182 | }, 1183 | "autoload": { 1184 | "classmap": [ 1185 | "src/" 1186 | ] 1187 | }, 1188 | "notification-url": "https://packagist.org/downloads/", 1189 | "license": [ 1190 | "BSD-3-Clause" 1191 | ], 1192 | "authors": [ 1193 | { 1194 | "name": "Kore Nordmann", 1195 | "email": "mail@kore-nordmann.de" 1196 | }, 1197 | { 1198 | "name": "Sebastian Bergmann", 1199 | "email": "sebastian@phpunit.de" 1200 | } 1201 | ], 1202 | "description": "Diff implementation", 1203 | "homepage": "http://www.github.com/sebastianbergmann/diff", 1204 | "keywords": [ 1205 | "diff" 1206 | ], 1207 | "time": "2015-02-22 15:13:53" 1208 | }, 1209 | { 1210 | "name": "sebastian/exporter", 1211 | "version": "1.2.1", 1212 | "source": { 1213 | "type": "git", 1214 | "url": "https://github.com/sebastianbergmann/exporter.git", 1215 | "reference": "7ae5513327cb536431847bcc0c10edba2701064e" 1216 | }, 1217 | "dist": { 1218 | "type": "zip", 1219 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", 1220 | "reference": "7ae5513327cb536431847bcc0c10edba2701064e", 1221 | "shasum": "" 1222 | }, 1223 | "require": { 1224 | "php": ">=5.3.3", 1225 | "sebastian/recursion-context": "~1.0" 1226 | }, 1227 | "require-dev": { 1228 | "phpunit/phpunit": "~4.4" 1229 | }, 1230 | "type": "library", 1231 | "extra": { 1232 | "branch-alias": { 1233 | "dev-master": "1.2.x-dev" 1234 | } 1235 | }, 1236 | "autoload": { 1237 | "classmap": [ 1238 | "src/" 1239 | ] 1240 | }, 1241 | "notification-url": "https://packagist.org/downloads/", 1242 | "license": [ 1243 | "BSD-3-Clause" 1244 | ], 1245 | "authors": [ 1246 | { 1247 | "name": "Jeff Welch", 1248 | "email": "whatthejeff@gmail.com" 1249 | }, 1250 | { 1251 | "name": "Volker Dusch", 1252 | "email": "github@wallbash.com" 1253 | }, 1254 | { 1255 | "name": "Bernhard Schussek", 1256 | "email": "bschussek@2bepublished.at" 1257 | }, 1258 | { 1259 | "name": "Sebastian Bergmann", 1260 | "email": "sebastian@phpunit.de" 1261 | }, 1262 | { 1263 | "name": "Adam Harvey", 1264 | "email": "aharvey@php.net" 1265 | } 1266 | ], 1267 | "description": "Provides the functionality to export PHP variables for visualization", 1268 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1269 | "keywords": [ 1270 | "export", 1271 | "exporter" 1272 | ], 1273 | "time": "2015-06-21 07:55:53" 1274 | }, 1275 | { 1276 | "name": "sebastian/recursion-context", 1277 | "version": "1.0.1", 1278 | "source": { 1279 | "type": "git", 1280 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1281 | "reference": "994d4a811bafe801fb06dccbee797863ba2792ba" 1282 | }, 1283 | "dist": { 1284 | "type": "zip", 1285 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba", 1286 | "reference": "994d4a811bafe801fb06dccbee797863ba2792ba", 1287 | "shasum": "" 1288 | }, 1289 | "require": { 1290 | "php": ">=5.3.3" 1291 | }, 1292 | "require-dev": { 1293 | "phpunit/phpunit": "~4.4" 1294 | }, 1295 | "type": "library", 1296 | "extra": { 1297 | "branch-alias": { 1298 | "dev-master": "1.0.x-dev" 1299 | } 1300 | }, 1301 | "autoload": { 1302 | "classmap": [ 1303 | "src/" 1304 | ] 1305 | }, 1306 | "notification-url": "https://packagist.org/downloads/", 1307 | "license": [ 1308 | "BSD-3-Clause" 1309 | ], 1310 | "authors": [ 1311 | { 1312 | "name": "Jeff Welch", 1313 | "email": "whatthejeff@gmail.com" 1314 | }, 1315 | { 1316 | "name": "Sebastian Bergmann", 1317 | "email": "sebastian@phpunit.de" 1318 | }, 1319 | { 1320 | "name": "Adam Harvey", 1321 | "email": "aharvey@php.net" 1322 | } 1323 | ], 1324 | "description": "Provides functionality to recursively process PHP variables", 1325 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1326 | "time": "2015-06-21 08:04:50" 1327 | }, 1328 | { 1329 | "name": "symfony/console", 1330 | "version": "v2.7.3", 1331 | "source": { 1332 | "type": "git", 1333 | "url": "https://github.com/symfony/Console.git", 1334 | "reference": "d6cf02fe73634c96677e428f840704bfbcaec29e" 1335 | }, 1336 | "dist": { 1337 | "type": "zip", 1338 | "url": "https://api.github.com/repos/symfony/Console/zipball/d6cf02fe73634c96677e428f840704bfbcaec29e", 1339 | "reference": "d6cf02fe73634c96677e428f840704bfbcaec29e", 1340 | "shasum": "" 1341 | }, 1342 | "require": { 1343 | "php": ">=5.3.9" 1344 | }, 1345 | "require-dev": { 1346 | "psr/log": "~1.0", 1347 | "symfony/event-dispatcher": "~2.1", 1348 | "symfony/phpunit-bridge": "~2.7", 1349 | "symfony/process": "~2.1" 1350 | }, 1351 | "suggest": { 1352 | "psr/log": "For using the console logger", 1353 | "symfony/event-dispatcher": "", 1354 | "symfony/process": "" 1355 | }, 1356 | "type": "library", 1357 | "extra": { 1358 | "branch-alias": { 1359 | "dev-master": "2.7-dev" 1360 | } 1361 | }, 1362 | "autoload": { 1363 | "psr-4": { 1364 | "Symfony\\Component\\Console\\": "" 1365 | } 1366 | }, 1367 | "notification-url": "https://packagist.org/downloads/", 1368 | "license": [ 1369 | "MIT" 1370 | ], 1371 | "authors": [ 1372 | { 1373 | "name": "Fabien Potencier", 1374 | "email": "fabien@symfony.com" 1375 | }, 1376 | { 1377 | "name": "Symfony Community", 1378 | "homepage": "https://symfony.com/contributors" 1379 | } 1380 | ], 1381 | "description": "Symfony Console Component", 1382 | "homepage": "https://symfony.com", 1383 | "time": "2015-07-28 15:18:12" 1384 | }, 1385 | { 1386 | "name": "symfony/event-dispatcher", 1387 | "version": "v2.7.3", 1388 | "source": { 1389 | "type": "git", 1390 | "url": "https://github.com/symfony/EventDispatcher.git", 1391 | "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3" 1392 | }, 1393 | "dist": { 1394 | "type": "zip", 1395 | "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/9310b5f9a87ec2ea75d20fec0b0017c77c66dac3", 1396 | "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3", 1397 | "shasum": "" 1398 | }, 1399 | "require": { 1400 | "php": ">=5.3.9" 1401 | }, 1402 | "require-dev": { 1403 | "psr/log": "~1.0", 1404 | "symfony/config": "~2.0,>=2.0.5", 1405 | "symfony/dependency-injection": "~2.6", 1406 | "symfony/expression-language": "~2.6", 1407 | "symfony/phpunit-bridge": "~2.7", 1408 | "symfony/stopwatch": "~2.3" 1409 | }, 1410 | "suggest": { 1411 | "symfony/dependency-injection": "", 1412 | "symfony/http-kernel": "" 1413 | }, 1414 | "type": "library", 1415 | "extra": { 1416 | "branch-alias": { 1417 | "dev-master": "2.7-dev" 1418 | } 1419 | }, 1420 | "autoload": { 1421 | "psr-4": { 1422 | "Symfony\\Component\\EventDispatcher\\": "" 1423 | } 1424 | }, 1425 | "notification-url": "https://packagist.org/downloads/", 1426 | "license": [ 1427 | "MIT" 1428 | ], 1429 | "authors": [ 1430 | { 1431 | "name": "Fabien Potencier", 1432 | "email": "fabien@symfony.com" 1433 | }, 1434 | { 1435 | "name": "Symfony Community", 1436 | "homepage": "https://symfony.com/contributors" 1437 | } 1438 | ], 1439 | "description": "Symfony EventDispatcher Component", 1440 | "homepage": "https://symfony.com", 1441 | "time": "2015-06-18 19:21:56" 1442 | }, 1443 | { 1444 | "name": "symfony/finder", 1445 | "version": "v2.7.3", 1446 | "source": { 1447 | "type": "git", 1448 | "url": "https://github.com/symfony/Finder.git", 1449 | "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4" 1450 | }, 1451 | "dist": { 1452 | "type": "zip", 1453 | "url": "https://api.github.com/repos/symfony/Finder/zipball/ae0f363277485094edc04c9f3cbe595b183b78e4", 1454 | "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4", 1455 | "shasum": "" 1456 | }, 1457 | "require": { 1458 | "php": ">=5.3.9" 1459 | }, 1460 | "require-dev": { 1461 | "symfony/phpunit-bridge": "~2.7" 1462 | }, 1463 | "type": "library", 1464 | "extra": { 1465 | "branch-alias": { 1466 | "dev-master": "2.7-dev" 1467 | } 1468 | }, 1469 | "autoload": { 1470 | "psr-4": { 1471 | "Symfony\\Component\\Finder\\": "" 1472 | } 1473 | }, 1474 | "notification-url": "https://packagist.org/downloads/", 1475 | "license": [ 1476 | "MIT" 1477 | ], 1478 | "authors": [ 1479 | { 1480 | "name": "Fabien Potencier", 1481 | "email": "fabien@symfony.com" 1482 | }, 1483 | { 1484 | "name": "Symfony Community", 1485 | "homepage": "https://symfony.com/contributors" 1486 | } 1487 | ], 1488 | "description": "Symfony Finder Component", 1489 | "homepage": "https://symfony.com", 1490 | "time": "2015-07-09 16:07:40" 1491 | }, 1492 | { 1493 | "name": "symfony/process", 1494 | "version": "v2.7.3", 1495 | "source": { 1496 | "type": "git", 1497 | "url": "https://github.com/symfony/Process.git", 1498 | "reference": "48aeb0e48600321c272955132d7606ab0a49adb3" 1499 | }, 1500 | "dist": { 1501 | "type": "zip", 1502 | "url": "https://api.github.com/repos/symfony/Process/zipball/48aeb0e48600321c272955132d7606ab0a49adb3", 1503 | "reference": "48aeb0e48600321c272955132d7606ab0a49adb3", 1504 | "shasum": "" 1505 | }, 1506 | "require": { 1507 | "php": ">=5.3.9" 1508 | }, 1509 | "require-dev": { 1510 | "symfony/phpunit-bridge": "~2.7" 1511 | }, 1512 | "type": "library", 1513 | "extra": { 1514 | "branch-alias": { 1515 | "dev-master": "2.7-dev" 1516 | } 1517 | }, 1518 | "autoload": { 1519 | "psr-4": { 1520 | "Symfony\\Component\\Process\\": "" 1521 | } 1522 | }, 1523 | "notification-url": "https://packagist.org/downloads/", 1524 | "license": [ 1525 | "MIT" 1526 | ], 1527 | "authors": [ 1528 | { 1529 | "name": "Fabien Potencier", 1530 | "email": "fabien@symfony.com" 1531 | }, 1532 | { 1533 | "name": "Symfony Community", 1534 | "homepage": "https://symfony.com/contributors" 1535 | } 1536 | ], 1537 | "description": "Symfony Process Component", 1538 | "homepage": "https://symfony.com", 1539 | "time": "2015-07-01 11:25:50" 1540 | }, 1541 | { 1542 | "name": "symfony/yaml", 1543 | "version": "v2.7.3", 1544 | "source": { 1545 | "type": "git", 1546 | "url": "https://github.com/symfony/Yaml.git", 1547 | "reference": "71340e996171474a53f3d29111d046be4ad8a0ff" 1548 | }, 1549 | "dist": { 1550 | "type": "zip", 1551 | "url": "https://api.github.com/repos/symfony/Yaml/zipball/71340e996171474a53f3d29111d046be4ad8a0ff", 1552 | "reference": "71340e996171474a53f3d29111d046be4ad8a0ff", 1553 | "shasum": "" 1554 | }, 1555 | "require": { 1556 | "php": ">=5.3.9" 1557 | }, 1558 | "require-dev": { 1559 | "symfony/phpunit-bridge": "~2.7" 1560 | }, 1561 | "type": "library", 1562 | "extra": { 1563 | "branch-alias": { 1564 | "dev-master": "2.7-dev" 1565 | } 1566 | }, 1567 | "autoload": { 1568 | "psr-4": { 1569 | "Symfony\\Component\\Yaml\\": "" 1570 | } 1571 | }, 1572 | "notification-url": "https://packagist.org/downloads/", 1573 | "license": [ 1574 | "MIT" 1575 | ], 1576 | "authors": [ 1577 | { 1578 | "name": "Fabien Potencier", 1579 | "email": "fabien@symfony.com" 1580 | }, 1581 | { 1582 | "name": "Symfony Community", 1583 | "homepage": "https://symfony.com/contributors" 1584 | } 1585 | ], 1586 | "description": "Symfony Yaml Component", 1587 | "homepage": "https://symfony.com", 1588 | "time": "2015-07-28 14:07:07" 1589 | }, 1590 | { 1591 | "name": "twig/twig", 1592 | "version": "v1.21.1", 1593 | "source": { 1594 | "type": "git", 1595 | "url": "https://github.com/twigphp/Twig.git", 1596 | "reference": "ca8d3aa90b6a01c82e07909fe815d6b443e75a23" 1597 | }, 1598 | "dist": { 1599 | "type": "zip", 1600 | "url": "https://api.github.com/repos/twigphp/Twig/zipball/ca8d3aa90b6a01c82e07909fe815d6b443e75a23", 1601 | "reference": "ca8d3aa90b6a01c82e07909fe815d6b443e75a23", 1602 | "shasum": "" 1603 | }, 1604 | "require": { 1605 | "php": ">=5.2.7" 1606 | }, 1607 | "require-dev": { 1608 | "symfony/debug": "~2.7", 1609 | "symfony/phpunit-bridge": "~2.7" 1610 | }, 1611 | "type": "library", 1612 | "extra": { 1613 | "branch-alias": { 1614 | "dev-master": "1.21-dev" 1615 | } 1616 | }, 1617 | "autoload": { 1618 | "psr-0": { 1619 | "Twig_": "lib/" 1620 | } 1621 | }, 1622 | "notification-url": "https://packagist.org/downloads/", 1623 | "license": [ 1624 | "BSD-3-Clause" 1625 | ], 1626 | "authors": [ 1627 | { 1628 | "name": "Fabien Potencier", 1629 | "email": "fabien@symfony.com", 1630 | "homepage": "http://fabien.potencier.org", 1631 | "role": "Lead Developer" 1632 | }, 1633 | { 1634 | "name": "Armin Ronacher", 1635 | "email": "armin.ronacher@active-4.com", 1636 | "role": "Project Founder" 1637 | }, 1638 | { 1639 | "name": "Twig Team", 1640 | "homepage": "http://twig.sensiolabs.org/contributors", 1641 | "role": "Contributors" 1642 | } 1643 | ], 1644 | "description": "Twig, the flexible, fast, and secure template language for PHP", 1645 | "homepage": "http://twig.sensiolabs.org", 1646 | "keywords": [ 1647 | "templating" 1648 | ], 1649 | "time": "2015-08-26 08:58:31" 1650 | } 1651 | ], 1652 | "aliases": [], 1653 | "minimum-stability": "stable", 1654 | "stability-flags": [], 1655 | "prefer-stable": false, 1656 | "prefer-lowest": false, 1657 | "platform": { 1658 | "php": ">=5.4" 1659 | }, 1660 | "platform-dev": [] 1661 | } 1662 | -------------------------------------------------------------------------------- /data/GeoLite2-Country.mmdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umpirsky/locurro/a0512a4e60460a7b96448470fd9a63f2e1dcd79f/data/GeoLite2-Country.mmdb -------------------------------------------------------------------------------- /examples/country.php: -------------------------------------------------------------------------------- 1 | convert( 18 | new Money\Money(100, new Money\Currency('EUR')), 19 | 'RS' 20 | ); 21 | 22 | var_dump($money); 23 | -------------------------------------------------------------------------------- /examples/currency.php: -------------------------------------------------------------------------------- 1 | convert( 14 | new Money\Money(100, new Money\Currency('EUR')), 15 | new Money\Currency('RSD') 16 | ); 17 | 18 | var_dump($money); 19 | -------------------------------------------------------------------------------- /examples/ip-cached.php: -------------------------------------------------------------------------------- 1 | convert( 27 | new Money\Money(100, new Money\Currency('EUR')), 28 | '109.92.115.78' 29 | ); 30 | 31 | var_dump($money); 32 | -------------------------------------------------------------------------------- /examples/ip-chained.php: -------------------------------------------------------------------------------- 1 | convert( 28 | new Money\Money(100, new Money\Currency('EUR')), 29 | '109.92.115.78' 30 | ); 31 | 32 | var_dump($money); 33 | -------------------------------------------------------------------------------- /examples/ip.php: -------------------------------------------------------------------------------- 1 | convert( 26 | new Money\Money(100, new Money\Currency('EUR')), 27 | '109.92.115.78' 28 | ); 29 | 30 | var_dump($money); 31 | -------------------------------------------------------------------------------- /examples/locale.php: -------------------------------------------------------------------------------- 1 | convert( 16 | new Money\Money(100, new Money\Currency('EUR')), 17 | 'sr-Cyrl-RS' 18 | ); 19 | 20 | var_dump($money); 21 | -------------------------------------------------------------------------------- /img/fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umpirsky/locurro/a0512a4e60460a7b96448470fd9a63f2e1dcd79f/img/fr.png -------------------------------------------------------------------------------- /img/us.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umpirsky/locurro/a0512a4e60460a7b96448470fd9a63f2e1dcd79f/img/us.png -------------------------------------------------------------------------------- /spec/Locurro/Converter/CountrySpec.php: -------------------------------------------------------------------------------- 1 | beConstructedWith($converter); 15 | } 16 | 17 | function it_is_initializable() 18 | { 19 | $this->shouldHaveType('Locurro\Converter\Country'); 20 | } 21 | 22 | function it_implements_currency_converter_interface() 23 | { 24 | $this->shouldImplement('Locurro\Converter\ConverterInterface'); 25 | } 26 | 27 | function it_converts_money_using_locale_converter(Locale $converter, Money $money, Money $converted) 28 | { 29 | $converter->convert($money, 'sr_Cyrl_RS')->shouldBeCalled()->willReturn($converted); 30 | 31 | $this->convert($money, 'RS')->shouldBeEqualTo($converted); 32 | } 33 | 34 | function it_throws_exception_if_country_is_invalid(Money $money) 35 | { 36 | $this->shouldThrow('Locurro\Exception\InvalidCountryException')->duringConvert($money, 'umpirsky'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /spec/Locurro/Converter/CurrencySpec.php: -------------------------------------------------------------------------------- 1 | beConstructedWith($swap); 17 | } 18 | 19 | function it_is_initializable() 20 | { 21 | $this->shouldHaveType('Locurro\Converter\Currency'); 22 | } 23 | 24 | function it_implements_currency_converter_interface() 25 | { 26 | $this->shouldImplement('Locurro\Converter\ConverterInterface'); 27 | } 28 | 29 | function it_converts_money(SwapInterface $swap, Money $money, Currency $currency) 30 | { 31 | $money->getAmount()->willReturn(5); 32 | $money->getCurrency()->willReturn($currency); 33 | $money->multiply(5)->willReturn($money); 34 | 35 | $currency->__toString()->willReturn('EUR'); 36 | 37 | $swap->quote(Argument::any())->shouldBeCalled()->willReturn(new Rate(5)); 38 | 39 | $this->convert($money, $currency)->shouldHaveType('Money\Money'); 40 | } 41 | 42 | function it_converts_money_based_on_given_currency(SwapInterface $swap, Money $money, Currency $currency) 43 | { 44 | $money->getAmount()->willReturn(5); 45 | $money->getCurrency()->willReturn($currency); 46 | $money->multiply(5)->willReturn($money); 47 | 48 | $currency->__toString()->willReturn('EUR'); 49 | 50 | $swap->quote(Argument::any())->shouldBeCalled()->willReturn(new Rate(5)); 51 | 52 | $this->convert($money, $currency)->getCurrency()->shouldBe($currency); 53 | } 54 | 55 | function it_converts_money_using_swap(SwapInterface $swap, Money $money, Money $converted, Currency $from, Currency $to) 56 | { 57 | $money->getAmount()->willReturn(100); 58 | $money->getCurrency()->willReturn($from); 59 | $money->multiply(120.3971)->willReturn($converted); 60 | 61 | $converted->getAmount()->willReturn(12039); 62 | $converted->getCurrency()->willReturn($to); 63 | 64 | $from->__toString()->willReturn('EUR'); 65 | $to->__toString()->willReturn('RSD'); 66 | 67 | $rate = new Rate(120.3971); 68 | 69 | $swap->quote('EUR/RSD')->shouldBeCalled()->willReturn($rate); 70 | 71 | $this->convert($money, $to)->getAmount()->shouldBe(12039); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /spec/Locurro/Converter/IpAddressSpec.php: -------------------------------------------------------------------------------- 1 | beConstructedWith($converter, $geocoder); 19 | } 20 | 21 | function it_is_initializable() 22 | { 23 | $this->shouldHaveType('Locurro\Converter\IpAddress'); 24 | } 25 | 26 | function it_implements_currency_converter_interface() 27 | { 28 | $this->shouldImplement('Locurro\Converter\ConverterInterface'); 29 | } 30 | 31 | function it_converts_money_using_country_converter(CountryConverter $converter, Geocoder $geocoder, Money $money, Money $converted) 32 | { 33 | $country = new Country('Serbia', 'RS'); 34 | $address = new Address(null, null, null, null, null, null, null, null, $country); 35 | $addresses = new AddressCollection([$address]); 36 | 37 | $geocoder->geocode('109.92.115.78')->shouldBeCalled()->willReturn($addresses); 38 | $converter->convert($money, 'RS')->shouldBeCalled()->willReturn($converted); 39 | 40 | $this->convert($money, '109.92.115.78')->shouldBeEqualTo($converted); 41 | } 42 | 43 | function it_throws_exception_if_country_is_not_geolocated(Geocoder $geocoder, Money $money) 44 | { 45 | $geocoder->geocode(Argument::any())->shouldBeCalled()->willReturn(new AddressCollection()); 46 | 47 | $this->shouldThrow('Locurro\Exception\GeolocationException')->duringConvert($money, 'umpirsky'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /spec/Locurro/Converter/LocaleSpec.php: -------------------------------------------------------------------------------- 1 | beConstructedWith($currencyConverter); 16 | } 17 | 18 | function it_implements_currency_converter_interface() 19 | { 20 | $this->shouldImplement('Locurro\Converter\ConverterInterface'); 21 | } 22 | 23 | function it_is_initializable() 24 | { 25 | $this->shouldHaveType('Locurro\Converter\Locale'); 26 | } 27 | 28 | function it_converts_money_using_currency_converter(CurrencyConverter $currencyConverter, Money $money, Money $converted) 29 | { 30 | $currencyConverter->convert($money, Argument::any())->shouldBeCalled()->willReturn($converted); 31 | 32 | $this->convert($money, 'sr_Cyrl_RS')->shouldBeEqualTo($converted); 33 | } 34 | 35 | function it_throws_exception_if_locale_is_invalid(CurrencyConverter $currencyConverter, Money $money) 36 | { 37 | $this->shouldThrow('Locurro\Exception\InvalidLocaleException')->duringConvert($money, 'umpirsky'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /spec/Locurro/Twig/ExtensionSpec.php: -------------------------------------------------------------------------------- 1 | beConstructedWith($converter); 15 | } 16 | 17 | function it_is_initializable() 18 | { 19 | $this->shouldHaveType('Locurro\Twig\Extension'); 20 | } 21 | 22 | function it_is_a_twig_extension() 23 | { 24 | $this->shouldHaveType('Twig_Extension'); 25 | } 26 | 27 | function it_converts_using_locurro_converter(ConverterInterface $converter, Money $money) 28 | { 29 | $converter->convert($money, 'sr')->shouldBeCalled()->willReturn($money); 30 | 31 | $this->convert($money, 'sr')->shouldHaveType('Money\Money'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Locurro/Converter/ConverterInterface.php: -------------------------------------------------------------------------------- 1 | converter = $converter; 15 | } 16 | 17 | public function convert(Money $money, $target) 18 | { 19 | $locale = \Zend_Locale::getLocaleToTerritory($target); 20 | 21 | if (null === $locale) { 22 | throw new InvalidCountryException(sprintf( 23 | 'Cannot find locale for "%s" country.', 24 | $target 25 | )); 26 | } 27 | 28 | return $this->converter->convert($money, $locale); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Locurro/Converter/Currency.php: -------------------------------------------------------------------------------- 1 | swap = $swap; 18 | } 19 | 20 | public function convert(Money $money, $target) 21 | { 22 | if (!$target instanceof MoneyCurrency) { 23 | throw new InvalidArgumentException(sprintf( 24 | 'Second argument must be Currency, %s given.', 25 | gettype($target) 26 | )); 27 | } 28 | 29 | $rate = $this->swap->quote( 30 | new CurrencyPair($money->getCurrency(), $target) 31 | ); 32 | 33 | return new Money( 34 | $money->multiply( 35 | (float) $rate->getValue() 36 | )->getAmount(), 37 | $target 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Locurro/Converter/IpAddress.php: -------------------------------------------------------------------------------- 1 | converter = $converter; 18 | $this->geocoder = $geocoder; 19 | } 20 | 21 | public function convert(Money $money, $target) 22 | { 23 | try { 24 | $country = $this->geocoder->geocode($target)->first()->getCountry(); 25 | } catch (CollectionIsEmpty $e) { 26 | throw new GeolocationException(sprintf( 27 | 'Cannot geolocate "%s".', 28 | $target 29 | ), $e); 30 | } 31 | 32 | return $this->converter->convert($money, $country->getCode()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Locurro/Converter/Locale.php: -------------------------------------------------------------------------------- 1 | converter = $converter; 16 | } 17 | 18 | public function convert(Money $money, $target) 19 | { 20 | $currencyCode = $this->getCurrencyCode($target); 21 | 22 | return $this->converter->convert( 23 | $money, 24 | new MoneyCurrency($currencyCode) 25 | ); 26 | } 27 | 28 | private function getCurrencyCode($locale) 29 | { 30 | try { 31 | $currencyCode = (new \Zend_Currency(null, $locale))->getShortName(); 32 | if (null === $currencyCode) { 33 | throw new InvalidLocaleException(sprintf( 34 | 'Cannot find currency for "%s" locale.', 35 | $locale 36 | )); 37 | } 38 | } catch (\Exception $e) { 39 | throw new InvalidLocaleException(sprintf( 40 | 'Cannot find currency for "%s" locale.', 41 | $locale 42 | ), $e->getCode(), $e); 43 | } 44 | 45 | return $currencyCode; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Locurro/Exception/Exception.php: -------------------------------------------------------------------------------- 1 | getCode(), $previous); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Locurro/Exception/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | converter = $converter; 15 | } 16 | 17 | public function getFilters() 18 | { 19 | return [ 20 | new \Twig_SimpleFilter('locurro_convert', [$this, 'convert']), 21 | ]; 22 | } 23 | 24 | public function convert(Money $money, $target) 25 | { 26 | return $this->converter->convert($money, $target); 27 | } 28 | 29 | public function getName() 30 | { 31 | return 'locurro'; 32 | } 33 | } 34 | --------------------------------------------------------------------------------