From 72a655bc1ca08ac8ff6c7f51ce47a8d09c0dc22a Mon Sep 17 00:00:00 2001 From: gustavodscruz Date: Fri, 1 Aug 2025 20:42:49 -0300 Subject: [PATCH 1/7] feat: currency converter --- .htaccess | 7 +++++++ src/ExchangeController.php | 38 ++++++++++++++++++++++++++++++++++++++ src/Utils/Response.php | 37 +++++++++++++++++++++++++++++++++++++ src/index.php | 27 +++++++++++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 .htaccess create mode 100644 src/ExchangeController.php create mode 100644 src/Utils/Response.php diff --git a/.htaccess b/.htaccess new file mode 100644 index 00000000..a174a4a7 --- /dev/null +++ b/.htaccess @@ -0,0 +1,7 @@ +RewriteEngine On + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d + +RewriteCond %{REQUEST_URI} ^/index\.php/(.*)$ +RewriteRule ^index\.php/(.*)$ /index.php?url=$1 [QSA,L] \ No newline at end of file diff --git a/src/ExchangeController.php b/src/ExchangeController.php new file mode 100644 index 00000000..f271d867 --- /dev/null +++ b/src/ExchangeController.php @@ -0,0 +1,38 @@ + ['EUR', 'USD'], + 'EUR' => ['BRL'], + 'USD' => ['BRL'] + ]; + + $symbols = [ + 'BRL' => 'R$', + 'USD' => '$', + 'EUR' => '€' + ]; + + if (!isset($supportedCurrencies[$from]) || !in_array($to, $supportedCurrencies[$from])) { + $response::exchangeNotSupported($from, $supportedCurrencies[$from]); + return; + } + + $convertedAmount = $amount * $rate; + + $response::exchangeOk($convertedAmount, $symbols[$to]); + } +} diff --git a/src/Utils/Response.php b/src/Utils/Response.php new file mode 100644 index 00000000..22c3daa3 --- /dev/null +++ b/src/Utils/Response.php @@ -0,0 +1,37 @@ + 'Rota não encontrada!'], 400); + } + + public static function exchangeNotSupported($from, $supportedCurrencies) + { + self::json([ + 'message' => "Moedas suportadas para " . $from . ": " . implode(', ', $supportedCurrencies) + ], 400); + } + + public static function exchangeOk($convertedAmount, $symbol) + { + self::json([ + 'data' => [ + 'valorConvertido' => $convertedAmount, + 'simboloMoeda' => $symbol + ] + ], 200); + } +} diff --git a/src/index.php b/src/index.php index 92841bc8..f90d6179 100644 --- a/src/index.php +++ b/src/index.php @@ -14,5 +14,32 @@ */ declare(strict_types=1); +use App\ExchangeController; +use App\Utils\Response; + require __DIR__ . '/../vendor/autoload.php'; + + +$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); + +if ($uri !== '/' && file_exists(__DIR__ . '/../../' . $uri)) { + Response::routeNotFound(); + return; +} + +$segments = explode('/', trim($uri, '/')); + + +if (!(count($segments) === 5 && $segments[0] === 'exchange')){ + Response::routeNotFound(); + return; +} + +ExchangeController::convert(new Response, $segments); + + + + + + From a52942b867400f51c1c25df38330086fa08753b5 Mon Sep 17 00:00:00 2001 From: gustavodscruz Date: Fri, 1 Aug 2025 21:56:38 -0300 Subject: [PATCH 2/7] fix: adjust value to be returned --- src/Utils/Response.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Utils/Response.php b/src/Utils/Response.php index 22c3daa3..626e21c4 100644 --- a/src/Utils/Response.php +++ b/src/Utils/Response.php @@ -28,10 +28,8 @@ public static function exchangeNotSupported($from, $supportedCurrencies) public static function exchangeOk($convertedAmount, $symbol) { self::json([ - 'data' => [ - 'valorConvertido' => $convertedAmount, - 'simboloMoeda' => $symbol - ] + 'valorConvertido' => $convertedAmount, + 'simboloMoeda' => $symbol ], 200); } } From 6ee09da22dacd04e956aab1e0edb8b04f28a4225 Mon Sep 17 00:00:00 2001 From: gustavodscruz Date: Fri, 1 Aug 2025 22:27:18 -0300 Subject: [PATCH 3/7] fix: adjusts of spaces and comments --- src/ExchangeController.php | 44 ++++++++++++++++++++- src/Utils/Response.php | 78 ++++++++++++++++++++++++++++++++++---- src/index.php | 4 +- 3 files changed, 116 insertions(+), 10 deletions(-) diff --git a/src/ExchangeController.php b/src/ExchangeController.php index f271d867..7f746ef1 100644 --- a/src/ExchangeController.php +++ b/src/ExchangeController.php @@ -1,11 +1,51 @@ + * @license http://opensource.org/licenses/MIT MIT + * @link https://github.com/apiki/back-end-challenge + */ namespace App; use App\Utils\Response; +/** + * Controlador para operações de conversão de moedas. + * + * Esta classe é responsável por processar solicitações de conversão + * entre diferentes moedas suportadas pela API, validando os parâmetros + * de entrada e retornando respostas formatadas. + * + * @category Challenge + * @package Back-end + * @author Gustavo Dias + * @license http://opensource.org/licenses/MIT MIT + * @link https://github.com/apiki/back-end-challenge + * @since 1.0.0 + */ class ExchangeController { + /** + * Converte um valor de uma moeda para outra. + * + * Este método processa os parâmetros de conversão, valida se a conversão + * é suportada entre as moedas especificadas, calcula o valor convertido + * usando a taxa fornecida e retorna uma resposta JSON formatada. + * + * @param Response $response Instância da classe Response para enviar a resposta + * @param array $params Array com os parâmetros: + * [0=>route, 1=>amount, 2=>from, 3=>to, 4=>rate] + * + * @return void + */ public static function convert(Response $response, array $params) { @@ -26,7 +66,9 @@ public static function convert(Response $response, array $params) 'EUR' => '€' ]; - if (!isset($supportedCurrencies[$from]) || !in_array($to, $supportedCurrencies[$from])) { + if (!isset($supportedCurrencies[$from]) + || !in_array($to, $supportedCurrencies[$from]) + ) { $response::exchangeNotSupported($from, $supportedCurrencies[$from]); return; } diff --git a/src/Utils/Response.php b/src/Utils/Response.php index 626e21c4..2fe3d854 100644 --- a/src/Utils/Response.php +++ b/src/Utils/Response.php @@ -1,9 +1,45 @@ + * @license http://opensource.org/licenses/MIT MIT + * @link https://github.com/apiki/back-end-challenge + */ + namespace App\Utils; +/** + * Classe utilitária para gerenciar respostas HTTP em formato JSON. + * + * Esta classe fornece métodos estáticos para padronizar as respostas + * da API, incluindo códigos de status HTTP apropriados e formatação + * consistente das mensagens de resposta. + * + * @category Challenge + * @package Back-end + * @author Gustavo Dias + * @license http://opensource.org/licenses/MIT MIT + * @link https://github.com/apiki/back-end-challenge + * @since 1.0.0 + */ class Response { + /** + * Envia uma resposta JSON com código de status HTTP. + * + * @param array $data Os dados a serem retornados em formato JSON + * @param int $status O código de status HTTP (padrão: 200) + * + * @return void + */ public static function json(array $data, int $status = 200) { http_response_code($status); @@ -13,23 +49,51 @@ public static function json(array $data, int $status = 200) echo json_encode($data); } + /** + * Retorna uma resposta JSON para rota não encontrada. + * + * @return void + */ public static function routeNotFound() { self::json(['message' => 'Rota não encontrada!'], 400); } + /** + * Retorna uma resposta JSON quando uma moeda não é suportada. + * + * @param string $from A moeda de origem + * @param array $supportedCurrencies Array com as moedas suportadas + * + * @return void + */ public static function exchangeNotSupported($from, $supportedCurrencies) { - self::json([ - 'message' => "Moedas suportadas para " . $from . ": " . implode(', ', $supportedCurrencies) - ], 400); + $formattedCurrencies = implode(', ', $supportedCurrencies); + self::json( + [ + 'message' => "Moedas suportadas para $from : $formattedCurrencies" + ], + 400 + ); } + /** + * Retorna uma resposta JSON de sucesso para conversão de moeda. + * + * @param float $convertedAmount O valor convertido + * @param string $symbol O símbolo da moeda de destino + * + * @return void + */ public static function exchangeOk($convertedAmount, $symbol) { - self::json([ - 'valorConvertido' => $convertedAmount, - 'simboloMoeda' => $symbol - ], 200); + self::json( + [ + 'valorConvertido' => $convertedAmount, + 'simboloMoeda' => $symbol + ], + 200 + ); } } diff --git a/src/index.php b/src/index.php index f90d6179..3f2e55c0 100644 --- a/src/index.php +++ b/src/index.php @@ -8,7 +8,7 @@ * * @category Challenge * @package Back-end - * @author Seu Nome + * @author Gustavo Dias * @license http://opensource.org/licenses/MIT MIT * @link https://github.com/apiki/back-end-challenge */ @@ -31,7 +31,7 @@ $segments = explode('/', trim($uri, '/')); -if (!(count($segments) === 5 && $segments[0] === 'exchange')){ +if (!(count($segments) === 5 && $segments[0] === 'exchange')) { Response::routeNotFound(); return; } From 3f39c269ae06aa28bf4f3f7000d34de047e9d72c Mon Sep 17 00:00:00 2001 From: gustavodscruz Date: Fri, 1 Aug 2025 22:38:56 -0300 Subject: [PATCH 4/7] fix: response class now on the root --- src/ExchangeController.php | 2 +- src/{Utils => }/Response.php | 2 +- src/index.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/{Utils => }/Response.php (99%) diff --git a/src/ExchangeController.php b/src/ExchangeController.php index 7f746ef1..1523363f 100644 --- a/src/ExchangeController.php +++ b/src/ExchangeController.php @@ -15,7 +15,7 @@ namespace App; -use App\Utils\Response; +use App\Response; /** * Controlador para operações de conversão de moedas. diff --git a/src/Utils/Response.php b/src/Response.php similarity index 99% rename from src/Utils/Response.php rename to src/Response.php index 2fe3d854..f3d324da 100644 --- a/src/Utils/Response.php +++ b/src/Response.php @@ -14,7 +14,7 @@ * @link https://github.com/apiki/back-end-challenge */ -namespace App\Utils; +namespace App; /** * Classe utilitária para gerenciar respostas HTTP em formato JSON. diff --git a/src/index.php b/src/index.php index 3f2e55c0..3464320c 100644 --- a/src/index.php +++ b/src/index.php @@ -15,7 +15,7 @@ declare(strict_types=1); use App\ExchangeController; -use App\Utils\Response; +use App\Response; require __DIR__ . '/../vendor/autoload.php'; From d38c2cf9b331989733a3705740185ba4ea269b37 Mon Sep 17 00:00:00 2001 From: gustavodscruz Date: Fri, 1 Aug 2025 22:56:33 -0300 Subject: [PATCH 5/7] fix: convert changes and cleaner comments --- src/ExchangeController.php | 13 +++++++------ src/index.php | 3 +-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ExchangeController.php b/src/ExchangeController.php index 1523363f..f6052e3e 100644 --- a/src/ExchangeController.php +++ b/src/ExchangeController.php @@ -40,13 +40,14 @@ class ExchangeController * é suportada entre as moedas especificadas, calcula o valor convertido * usando a taxa fornecida e retorna uma resposta JSON formatada. * - * @param Response $response Instância da classe Response para enviar a resposta - * @param array $params Array com os parâmetros: - * [0=>route, 1=>amount, 2=>from, 3=>to, 4=>rate] + * @param array $params Array com os + * parâmetros: [0=>route, + * 1=>amount, 2=>from, + * 3=>to, 4=>rate] * * @return void */ - public static function convert(Response $response, array $params) + public static function convert(array $params) { $amount = floatval($params[1]); @@ -69,12 +70,12 @@ public static function convert(Response $response, array $params) if (!isset($supportedCurrencies[$from]) || !in_array($to, $supportedCurrencies[$from]) ) { - $response::exchangeNotSupported($from, $supportedCurrencies[$from]); + Response::exchangeNotSupported($from, $supportedCurrencies[$from]); return; } $convertedAmount = $amount * $rate; - $response::exchangeOk($convertedAmount, $symbols[$to]); + Response::exchangeOk($convertedAmount, $symbols[$to]); } } diff --git a/src/index.php b/src/index.php index 3464320c..5444b539 100644 --- a/src/index.php +++ b/src/index.php @@ -20,7 +20,6 @@ require __DIR__ . '/../vendor/autoload.php'; - $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); if ($uri !== '/' && file_exists(__DIR__ . '/../../' . $uri)) { @@ -36,7 +35,7 @@ return; } -ExchangeController::convert(new Response, $segments); +ExchangeController::convert($segments); From 71c393735b4ed92b5f3b1a7b02b2f7ca3e538bfb Mon Sep 17 00:00:00 2001 From: gustavodscruz Date: Thu, 7 Aug 2025 18:41:49 -0300 Subject: [PATCH 6/7] fix: update PHP version requirement to 8.1.2 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ce7dfb19..0c067e6b 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Desafio para candidatos a back-end.", "type": "project", "require": { - "php": ">= 7.4" + "php": ">= 8.1.2" }, "require-dev": { "squizlabs/php_codesniffer": "^3.4", From 2e70e66aad255e83c82da19db7b4f2a6d85cf4f0 Mon Sep 17 00:00:00 2001 From: gustavodscruz Date: Thu, 7 Aug 2025 18:44:01 -0300 Subject: [PATCH 7/7] fix: update PHP version requirement to 8.1.2 in multiple files --- src/ExchangeController.php | 2 +- src/Response.php | 2 +- src/index.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ExchangeController.php b/src/ExchangeController.php index f6052e3e..6197d515 100644 --- a/src/ExchangeController.php +++ b/src/ExchangeController.php @@ -2,7 +2,7 @@ /** * Back-end Challenge. * - * PHP version 7.4 + * PHP version 8.1.2 * * Controlador responsável pela conversão de moedas. * diff --git a/src/Response.php b/src/Response.php index f3d324da..7aee3b09 100644 --- a/src/Response.php +++ b/src/Response.php @@ -3,7 +3,7 @@ /** * Back-end Challenge. * - * PHP version 7.4 + * PHP version 8.1.2 * * Este é o arquivo para respostas http em json. * diff --git a/src/index.php b/src/index.php index 5444b539..f8a181a2 100644 --- a/src/index.php +++ b/src/index.php @@ -2,7 +2,7 @@ /** * Back-end Challenge. * - * PHP version 7.4 + * PHP version 8.1.2 * * Este será o arquivo chamado na execução dos testes automátizados. *