Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions src/CurrencyConverter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php
/**
* Currency Converter.
*
* PHP version 7.4
*
* @category Challenge
* @package Back-end
* @author Seu Nome <seu-email@seu-provedor.com>
* @license http://opensource.org/licenses/MIT MIT
* @link https://github.com/apiki/back-end-challenge
*/

declare(strict_types=1);

namespace App;

/**
* Class CurrencyConverter
*
* @category Challenge
* @package Back-end
* @author Seu Nome <seu-email@seu-provedor.com>
* @license http://opensource.org/licenses/MIT MIT
* @link https://github.com/apiki/back-end-challenge
*/
class CurrencyConverter
{
private const CURRENCY_SYMBOLS = [
'USD' => '$',
'BRL' => 'R$',
'EUR' => '€',
];

private const VALID_CONVERSIONS = [
'BRL' => ['USD', 'EUR'],
'USD' => ['BRL'],
'EUR' => ['BRL'],
];

/**
* Convert currency.
*
* @param float $amount The amount to convert.
* @param string $from The source currency.
* @param string $to The target currency.
* @param float $rate The exchange rate.
*
* @return array
*/
public function convert(
float $amount,
string $from,
string $to,
float $rate
): array {
$this->_validate($amount, $from, $to, $rate);

$convertedValue = $amount * $rate;

return [
'valorConvertido' => $convertedValue,
'simboloMoeda' => self::CURRENCY_SYMBOLS[$to],
];
}

/**
* Validate conversion parameters.
*
* @param float $amount The amount to convert.
* @param string $from The source currency.
* @param string $to The target currency.
* @param float $rate The exchange rate.
*
* @return void
*
* @throws \InvalidArgumentException When parameters are invalid.
*/
private function _validate(
float $amount,
string $from,
string $to,
float $rate
): void {
if ($amount <= 0) {
throw new \InvalidArgumentException('Invalid amount.');
}

if ($rate <= 0) {
throw new \InvalidArgumentException('Invalid rate.');
}

if (!isset(self::CURRENCY_SYMBOLS[$from])) {
throw new \InvalidArgumentException('Invalid source currency.');
}

if (!isset(self::CURRENCY_SYMBOLS[$to])) {
throw new \InvalidArgumentException('Invalid target currency.');
}

if (!isset(self::VALID_CONVERSIONS[$from])
|| !in_array($to, self::VALID_CONVERSIONS[$from])
) {
throw new \InvalidArgumentException('Invalid conversion.');
}
}
}
90 changes: 90 additions & 0 deletions src/Router.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php
/**
* Router.
*
* PHP version 7.4
*
* @category Challenge
* @package Back-end
* @author Seu Nome <seu-email@seu-provedor.com>
* @license http://opensource.org/licenses/MIT MIT
* @link https://github.com/apiki/back-end-challenge
*/

declare(strict_types=1);

namespace App;

/**
* Class Router
*
* @category Challenge
* @package Back-end
* @author Seu Nome <seu-email@seu-provedor.com>
* @license http://opensource.org/licenses/MIT MIT
* @link https://github.com/apiki/back-end-challenge
*/
class Router
{
/**
* Handle the incoming request.
*
* @return void
*/
public function handleRequest(): void
{
header('Content-Type: application/json');

$uri = $_SERVER['REQUEST_URI'] ?? '';
$uri = parse_url($uri, PHP_URL_PATH);
$uri = preg_replace('#^/exchange#', '', $uri);

$parts = explode('/', trim($uri, '/'));

if (count($parts) < 4 || empty($parts[0])) {
$this->_sendError('Missing required parameters.', 400);
return;
}

list($amount, $from, $to, $rate) = $parts;

if (!is_numeric($amount) || !is_numeric($rate)) {
$this->_sendError('Invalid numeric value.', 400);
return;
}

if ($from !== strtoupper($from) || $to !== strtoupper($to)) {
$this->_sendError('Currency must be uppercase.', 400);
return;
}

try {
$converter = new CurrencyConverter();
$result = $converter->convert(
(float) $amount,
$from,
$to,
(float) $rate
);

http_response_code(200);
echo json_encode($result);
} catch (\InvalidArgumentException $e) {
$this->_sendError($e->getMessage(), 400);
}
}

/**
* Send an error response.
*
* @param string $message The error message.
* @param int $code The HTTP status code.
*
* @return void
*/
private function _sendError(string $message, int $code): void
{
http_response_code($code);
echo json_encode(['error' => $message]);
}
}
2 changes: 2 additions & 0 deletions src/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@

require __DIR__ . '/../vendor/autoload.php';

$router = new App\Router();
$router->handleRequest();
Loading