diff --git a/.htaccess b/.htaccess new file mode 100644 index 000000000..9e25198b5 --- /dev/null +++ b/.htaccess @@ -0,0 +1,4 @@ +RewriteEngine On +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ^(.*)$ index.php/$1 [L] \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..12dd25d65 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,24 @@ +{ + // Ignore Directory + "files.watcherExclude": { + "**/.git/objects/**": true, + "**/.git/subtree-cache/**": true, + "**/node_modules/*/**": true, + "**/.hg/store/**": true, + "**/vendor/*/**": true, + }, + "files.exclude": { + "**/.classpath": true, + "**/.project": true, + "**/.settings": true, + "**/.factorypath": true + }, + + // PHP Standard + "phpSniffer.standard": "./phpcs.xml", + "phpSniffer.autoDetect": true, + "[php]": { + "editor.defaultFormatter": "wongjn.php-sniffer", + "editor.formatOnSave": true + }, +} diff --git a/README.md b/README.md index 09e653c9c..6e32ed805 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,43 @@ # Back-end Challenge -Desafio para os futuros programadores back-end da Apiki. +Desafio back-end da Apiki. ## Introdução -Desenvolva uma **REST API** que faça conversão de moedas. +A **REST API** desenvolvida faz a conversão de moedas. -**Especifícações**: +## Instruções -* A URL da requisição deve seguir o seguinte formato: - * http://localhost:8000/exchange/{amount}/{from}/{to}/{rate} - * http://localhost:8000/exchange/10/BRL/USD/4.50 -* A resposta deve seguir o seguinte formato: +1. Clonar o repositório: `git clone https://github.com/luispaiva/back-end-challenge`; +1. Troque de branch: `git checkout luis-paiva`; +2. Instalar as dependências utilizando composer: `composer install`; +3. Levantar servidor embutido do PHP: `php -S localhost:8000 index.php`; +4. Executar o lint do código: `composer lint`; +5. Executar os testes: `composer test`; + +**Especificações**: + +* Para realizar os testes com o servidor web embutido do PHP, esse é o formato da URL: + * http://localhost:8000/index.php/exchange/{amount}/{from}/{to}/{rate} + * http://localhost:8000/index.php/exchange/10/BRL/USD/4.50 + +
+ + *Obs.: Você deve usar `index.php/exchange/10/BRL/USD/4.50` em vez de `exchange/10/BRL/USD/4.50` na URL para garantir que o servidor web embutido do PHP chame o arquivo principal index.php.* +
+ +* Para realizar os testes em localhost, esse é o formato da URL: + * http://localhost/back-end-challenge/exchange/{amount}/{from}/{to}/{rate} + * http://localhost/back-end-challenge/exchange/10/BRL/USD/4.50 + +* A resposta segue o seguinte formato: ```json { "valorConvertido": 45, "simboloMoeda": "$" } ``` -* Conversões: - * De Real para Dólar; - * De Dólar para Real; - * De Real para Euro; - * De Euro para Real; -* Serão executados testes automatizados para validação dos requisitos: - * Levantar servidor embutido do PHP: `php -S localhost:8000 index.php`; - * Executando testes: `composer test`; - * Executando lint: `composer lint`; - -## Instruções - -1. Efetue o fork deste repositório e crie um branch com o seu nome e sobrenome. (exemplo: fulano-dasilva) -2. Após finalizar o desafio, crie um Pull Request. -3. Aguarde algum contribuidor realizar o code review. - -*Obs.: Não esqueça de executar o `composer test` e `composer lint` localmente.* ## Pré-requisitos -* PHP => 7.4 -* Orientado a objetos - -## Dúvidas - -Em caso de dúvidas, crie uma issue. +* PHP => 7.4 \ No newline at end of file diff --git a/codeception.yml b/codeception.yml index e303d34e1..77569716f 100644 --- a/codeception.yml +++ b/codeception.yml @@ -6,7 +6,7 @@ suites: modules: enabled: - REST: - url: http://localhost:8000/exchange + url: http://localhost:8000/index.php/exchange depends: PhpBrowser paths: diff --git a/composer.json b/composer.json index ce7dfb195..716070a14 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,8 @@ "description": "Desafio para candidatos a back-end.", "type": "project", "require": { - "php": ">= 7.4" + "php": ">= 7.4", + "slim/slim": "3.*" }, "require-dev": { "squizlabs/php_codesniffer": "^3.4", diff --git a/composer.lock b/composer.lock index db54afa3a..254e98e7b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,290 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6936b33e616ca23e3f8d0517244d7829", - "packages": [], + "content-hash": "4572207432b7595eae0bfa5e3efa847c", + "packages": [ + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "FastRoute\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "support": { + "issues": "https://github.com/nikic/FastRoute/issues", + "source": "https://github.com/nikic/FastRoute/tree/master" + }, + "time": "2018-02-13T20:26:39+00:00" + }, + { + "name": "pimple/pimple", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a94b3a4db7fb774b3d78dad2315ddc07629e1bed", + "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1 || ^2.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^5.4@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "https://pimple.symfony.com", + "keywords": [ + "container", + "dependency injection" + ], + "support": { + "source": "https://github.com/silexphp/Pimple/tree/v3.5.0" + }, + "time": "2021-10-28T11:13:42+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "slim/slim", + "version": "3.12.3", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim.git", + "reference": "1c9318a84ffb890900901136d620b4f03a59da38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/1c9318a84ffb890900901136d620b4f03a59da38", + "reference": "1c9318a84ffb890900901136d620b4f03a59da38", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-libxml": "*", + "ext-simplexml": "*", + "nikic/fast-route": "^1.0", + "php": ">=5.5.0", + "pimple/pimple": "^3.0", + "psr/container": "^1.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + } + ], + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "homepage": "https://slimframework.com", + "keywords": [ + "api", + "framework", + "micro", + "router" + ], + "support": { + "issues": "https://github.com/slimphp/Slim/issues", + "source": "https://github.com/slimphp/Slim/tree/3.x" + }, + "time": "2019-11-28T17:40:33+00:00" + } + ], "packages-dev": [ { "name": "behat/gherkin", @@ -72,16 +354,16 @@ }, { "name": "codeception/codeception", - "version": "4.2.0", + "version": "4.2.1", "source": { "type": "git", "url": "https://github.com/Codeception/Codeception.git", - "reference": "e646d160bf1223d3595b227b69d903777fbcfb5f" + "reference": "77b3e2003fd4446b35826cb9dc397129c521c888" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/e646d160bf1223d3595b227b69d903777fbcfb5f", - "reference": "e646d160bf1223d3595b227b69d903777fbcfb5f", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/77b3e2003fd4446b35826cb9dc397129c521c888", + "reference": "77b3e2003fd4446b35826cb9dc397129c521c888", "shasum": "" }, "require": { @@ -158,7 +440,7 @@ ], "support": { "issues": "https://github.com/Codeception/Codeception/issues", - "source": "https://github.com/Codeception/Codeception/tree/4.2.0" + "source": "https://github.com/Codeception/Codeception/tree/4.2.1" }, "funding": [ { @@ -166,7 +448,7 @@ "type": "open_collective" } ], - "time": "2022-06-16T05:33:39+00:00" + "time": "2022-06-22T06:18:59+00:00" }, { "name": "codeception/lib-asserts", @@ -1819,54 +2101,6 @@ ], "time": "2022-06-19T12:14:25+00:00" }, - { - "name": "psr/container", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" - }, - "time": "2021-11-05T16:50:12+00:00" - }, { "name": "psr/event-dispatcher", "version": "1.0.0", @@ -2024,59 +2258,6 @@ }, "time": "2019-04-30T12:38:16+00:00" }, - { - "name": "psr/http-message", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/master" - }, - "time": "2016-08-06T14:39:51+00:00" - }, { "name": "ralouphie/getallheaders", "version": "3.0.3", @@ -3280,16 +3461,16 @@ }, { "name": "symfony/console", - "version": "v5.4.9", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb" + "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/829d5d1bf60b2efeb0887b7436873becc71a45eb", - "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb", + "url": "https://api.github.com/repos/symfony/console/zipball/4d671ab4ddac94ee439ea73649c69d9d200b5000", + "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000", "shasum": "" }, "require": { @@ -3359,7 +3540,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.9" + "source": "https://github.com/symfony/console/tree/v5.4.10" }, "funding": [ { @@ -3375,7 +3556,7 @@ "type": "tidelift" } ], - "time": "2022-05-18T06:17:34+00:00" + "time": "2022-06-26T13:00:04+00:00" }, { "name": "symfony/css-selector", @@ -3445,7 +3626,7 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -3492,7 +3673,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" }, "funding": [ { @@ -3672,7 +3853,7 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", @@ -3731,7 +3912,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" }, "funding": [ { @@ -4306,16 +4487,16 @@ }, { "name": "symfony/service-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c" + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c", - "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", "shasum": "" }, "require": { @@ -4369,7 +4550,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" }, "funding": [ { @@ -4385,20 +4566,20 @@ "type": "tidelift" } ], - "time": "2022-03-13T20:07:29+00:00" + "time": "2022-05-30T19:17:29+00:00" }, { "name": "symfony/string", - "version": "v5.4.9", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99" + "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/985e6a9703ef5ce32ba617c9c7d97873bb7b2a99", - "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99", + "url": "https://api.github.com/repos/symfony/string/zipball/4432bc7df82a554b3e413a8570ce2fea90e94097", + "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097", "shasum": "" }, "require": { @@ -4455,7 +4636,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.9" + "source": "https://github.com/symfony/string/tree/v5.4.10" }, "funding": [ { @@ -4471,20 +4652,20 @@ "type": "tidelift" } ], - "time": "2022-04-19T10:40:37+00:00" + "time": "2022-06-26T15:57:47+00:00" }, { "name": "symfony/yaml", - "version": "v5.4.3", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "e80f87d2c9495966768310fc531b487ce64237a2" + "reference": "04e42926429d9e8b39c174387ab990bf7817f7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/e80f87d2c9495966768310fc531b487ce64237a2", - "reference": "e80f87d2c9495966768310fc531b487ce64237a2", + "url": "https://api.github.com/repos/symfony/yaml/zipball/04e42926429d9e8b39c174387ab990bf7817f7a2", + "reference": "04e42926429d9e8b39c174387ab990bf7817f7a2", "shasum": "" }, "require": { @@ -4530,7 +4711,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.3" + "source": "https://github.com/symfony/yaml/tree/v5.4.10" }, "funding": [ { @@ -4546,7 +4727,7 @@ "type": "tidelift" } ], - "time": "2022-01-26T16:32:32+00:00" + "time": "2022-06-20T11:50:59+00:00" }, { "name": "theseer/tokenizer", diff --git a/index.php b/index.php index 249b94af4..db0005943 100644 --- a/index.php +++ b/index.php @@ -1,18 +1,28 @@ * @license http://opensource.org/licenses/MIT MIT - * @link https://github.com/apiki/back-end-challenge + * @link https://github.com/luispaiva/back-end-challenge/tree/luis-paiva */ + declare(strict_types=1); require __DIR__ . '/vendor/autoload.php'; +$config = ['settings' => ['displayErrorDetails' => true]]; +$container = new \Slim\Container($config); +$app = new \Slim\App($container); + +$app->get('/', '\App\Controllers\Exchange:init'); +$app->get('/exchange/', '\App\Controllers\Exchange:init'); +$app->get('/exchange[/{amount:[A-Za-z0-9.-]+}[/{from}[/{to}[/{rate:[A-Za-z0-9.-]+}]]]]', '\App\Controllers\Exchange:init'); +$app->run(); diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 000000000..383fd8015 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/Controllers/Exchange.php b/src/Controllers/Exchange.php new file mode 100644 index 000000000..0469f5036 --- /dev/null +++ b/src/Controllers/Exchange.php @@ -0,0 +1,80 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link https://github.com/luispaiva/back-end-challenge/tree/luis-paiva + */ + +namespace App\Controllers; + +use Psr\Http\Message\ServerRequestInterface as Request; +use Psr\Http\Message\ResponseInterface as Response; +use App\Helpers\Validate; + +/** + * Exchange class. + * + * @category Challenge + * @package Back-end + * @author Luis Paiva + * @license http://opensource.org/licenses/MIT MIT + * @link https://github.com/luispaiva/back-end-challenge/tree/luis-paiva + */ +final class Exchange +{ + /** + * Currency Symbols. + * + * @var array + */ + public $currencySymbol = [ + 'EUR' => '€', + 'USD' => '$', + 'BRL' => 'R$', + ]; + + /** + * Init. + * + * @param Request $request Request object. + * @param Response $response Response object. + * @param array $args Arguments. + * + * @return Response + */ + public function init(Request $request, Response $response, array $args): Response + { + $validate = Validate::args($args); + + if ($validate !== true) { + return $response->withJson($validate, $validate->code); + } + + $data = [ + 'valorConvertido' => $this->_convert($args['amount'], $args['rate']), + 'simboloMoeda' => $this->currencySymbol[$args['to']], + ]; + + return $response->withJson($data, 200); + } + + /** + * Convert values. + * + * @param int|float $amount Amount. + * @param int|float $rate Rate. + * + * @return float + */ + private function _convert($amount, $rate): float + { + return floatval(number_format($amount * $rate, 2, '.', '')); + } +} diff --git a/src/Helpers/Validate.php b/src/Helpers/Validate.php new file mode 100644 index 000000000..3cc5e1e5d --- /dev/null +++ b/src/Helpers/Validate.php @@ -0,0 +1,120 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link https://github.com/luispaiva/back-end-challenge/tree/luis-paiva. + */ + +namespace App\Helpers; + +/** + * Validate class. + * + * @category Validate. + * @package Back-end. + * @author Luis Paiva + * @license http://opensource.org/licenses/MIT MIT + * @link https://github.com/luispaiva/back-end-challenge/tree/luis-paiva. + */ +final class Validate +{ + /** + * Parameter names. + * + * @var array + */ + private static $_parameterNames = ['amount', 'from', 'to', 'rate']; + + /** + * From currency. + * + * @var array + */ + private static $_fromCurrency = ['EUR', 'USD', 'BRL']; + + /** + * To currency. + * + * @var array + */ + private static $_toCurrency = ['EUR', 'USD', 'BRL']; + + /** + * Validate args. + * + * @param array $args Arguments. + * + * @return \stdClass|true + */ + public static function args(array $args) + { + $error = new \stdClass(); + + if (empty($args)) { + $error->message = 'Missing parameters'; + $error->code = 400; + + return $error; + } + + foreach (self::$_parameterNames as $parameter) { + if (! isset($args[$parameter])) { + $error->message = "Missing {$parameter} parameter"; + $error->code = 400; + + return $error; + } + } + + if (! is_numeric($args['amount'])) { + $error->message = 'Invalid amount'; + $error->code = 400; + + return $error; + } + + if ($args['amount'] < 0) { + $error->message = 'Amount must be greater than 0'; + $error->code = 400; + + return $error; + } + + if (! in_array($args['from'], self::$_fromCurrency)) { + $error->message = 'Invalid from currency'; + $error->code = 400; + + return $error; + } + + if (! in_array($args['to'], self::$_toCurrency)) { + $error->message = 'Invalid to currency'; + $error->code = 400; + + return $error; + } + + if (! is_numeric($args['rate'])) { + $error->message = 'Invalid rate'; + $error->code = 400; + + return $error; + } + + if ($args['rate'] < 0) { + $error->message = 'Rate must be greater than 0'; + $error->code = 400; + + return $error; + } + + return true; + } +}