Add fxratesapi module for currency conversion functionality
Integrated a new fxratesapi module to handle currency conversions, including API configurations, rate conversion actions, and request logging. Added support for module settings such as enablement status, API key, and daily request limits. New routes, database interactions, and object handling were implemented to facilitate the module's operations.
This commit is contained in:
@@ -0,0 +1,518 @@
|
||||
<?php
|
||||
|
||||
namespace classes;
|
||||
|
||||
require_once WD . '/modules/fxratesapi/fxratesapi_c.php';
|
||||
/** Actions */
|
||||
require_once WD . '/modules/fxratesapi/actions/convert_rate_a.php';
|
||||
|
||||
use Exception;
|
||||
use fxratesapi\actions\convert_rate_a;
|
||||
use fxratesapi\fxratesapi_c;
|
||||
use interfaces\fxratesapi_i;
|
||||
use objects\fxratesapi_conversion_rates_o;
|
||||
|
||||
class fxratesapi implements fxratesapi_i
|
||||
{
|
||||
/**
|
||||
* Configuration of the fxratesapi module
|
||||
* @var fxratesapi_c
|
||||
*/
|
||||
public fxratesapi_c $config;
|
||||
|
||||
/**
|
||||
* API URL
|
||||
* @var string
|
||||
*/
|
||||
private string $api_url = 'https://api.fxratesapi.com/';
|
||||
|
||||
/**
|
||||
* ACTION: CONVERT RATE
|
||||
* @see convert_rate_a
|
||||
* @notation This action is when a currency conversion request is made, and logs the request in the database
|
||||
* @var convert_rate_a
|
||||
*/
|
||||
private convert_rate_a $convert_rate;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = new fxratesapi_c();
|
||||
/** Actions */
|
||||
$this->convert_rate = new convert_rate_a();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function isCached(string $base, string $target): bool
|
||||
{
|
||||
// Check if the base currency is valid
|
||||
self::requireValidCurrency($base);
|
||||
// Check if the target currency is valid
|
||||
self::requireValidCurrency($base);
|
||||
// Check if the request is cached
|
||||
$fxratesapi_lookups = new fxratesapi_conversion_rates_o();
|
||||
return $fxratesapi_lookups->isCached($base, $target);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function requireValidCurrency(string $currency): void
|
||||
{
|
||||
// Check if the currency is valid
|
||||
if (!preg_match('/^[A-Z]{3}$/', $currency)) {
|
||||
throw new Exception('Invalid currency');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function getCachedResponse(string $base, string $target): object
|
||||
{
|
||||
// Check if the base and target currencies are valid
|
||||
self::requireValidCurrency($base);
|
||||
self::requireValidCurrency($target);
|
||||
|
||||
// Get the cached response from the fxratesapi request log
|
||||
$fxratesapi_lookups = new fxratesapi_conversion_rates_o();
|
||||
$fxratesapi_lookups->getCachedResponse($base, $target);
|
||||
return $fxratesapi_lookups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception If the base or target currency is invalid
|
||||
* @throws Exception If the endpoint is invalid
|
||||
* @throws Exception If the response is invalid
|
||||
* @throws Exception If the response is not valid JSON
|
||||
* @throws Exception If the request fails
|
||||
*/
|
||||
function getConversionRate(string $base, string $target, string $endpoint, array $data): object
|
||||
{
|
||||
// Check if the base and target currencies are valid
|
||||
self::requireValidCurrency($base);
|
||||
self::requireValidCurrency($target);
|
||||
|
||||
// Send the request
|
||||
// Return the conversion rate
|
||||
return self::sendRequest($base, $target, $endpoint, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception If the module is not enabled, the license plate is invalid, the daily limit is exceeded, or the secret key is invalid
|
||||
*/
|
||||
function sendRequest(
|
||||
string $base,
|
||||
string $target,
|
||||
string $endpoint,
|
||||
array $data = [],
|
||||
string $method = 'GET'
|
||||
): object
|
||||
{
|
||||
// Validate the module is enabled
|
||||
self::requireModuleEnabled();
|
||||
// Validate the base and target currencies
|
||||
self::requireValidCurrency($base);
|
||||
self::requireValidCurrency($target);
|
||||
// Validate the daily limit
|
||||
self::requireDailyLimitNotExceeded();
|
||||
// Validate the secret key
|
||||
self::requireValidSecretKey();
|
||||
// Send the request
|
||||
$response = match ($method) {
|
||||
'GET' => self::sendGetRequest($base, $target, $endpoint, $data),
|
||||
'POST' => self::sendPostRequest($base, $target, $endpoint, $data),
|
||||
'PUT' => self::sendPutRequest($base, $target, $endpoint, $data),
|
||||
'DELETE' => self::sendDeleteRequest($base, $target, $endpoint, $data),
|
||||
default => self::exception(
|
||||
$base,
|
||||
$target,
|
||||
[
|
||||
'method' => $method,
|
||||
'endpoint' => $endpoint,
|
||||
'data' => $data,
|
||||
'license_plate' => $base,
|
||||
'response' => null,
|
||||
'status_code' => 400,
|
||||
'error' => 'Invalid request method',
|
||||
],
|
||||
500
|
||||
),
|
||||
};
|
||||
// Add the usage to the request log
|
||||
$this->convert_rate->convert_rate($base, $target, $response, 200);
|
||||
// Add the request to the log
|
||||
self::addRequestToLog($base, $target, $endpoint, $response);
|
||||
// Return the response
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function requireModuleEnabled(): void
|
||||
{
|
||||
// Check if the module is enabled
|
||||
if (!$this->config->enabled->isTrue()) {
|
||||
throw new Exception('The fxratesapi module is not enabled');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function requireDailyLimitNotExceeded(): void
|
||||
{
|
||||
// Check if the daily limit is exceeded
|
||||
if ($this->getDailyRequestCounter() >= $this->config->daily_limit->getVariableValue()) {
|
||||
throw new Exception('Daily limit exceeded');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function getDailyRequestCounter(): int
|
||||
{
|
||||
// Count the rows from the fxratesapi request log that was made today
|
||||
$fxratesapi_lookups = new fxratesapi_conversion_rates_o();
|
||||
$fxratesapi_lookups->getTodayCount();
|
||||
return $fxratesapi_lookups->getTodayCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function requireValidSecretKey(): void
|
||||
{
|
||||
// Check if the secret key is valid
|
||||
if ($this->config->secret_key->getVariableValue() === null) {
|
||||
self::exception(
|
||||
'',
|
||||
'',
|
||||
[
|
||||
'status_code' => 500,
|
||||
'error' => 'Invalid secret key defined in the config (fxratesapi_secret_key_c)',
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
function exception(string $base, string $target, array $data, int $status_code = 500): object
|
||||
{
|
||||
// Check if the response is valid JSON
|
||||
if (!json_decode($data['response'])) {
|
||||
throw new Exception('Invalid response');
|
||||
}
|
||||
// Add the request to the log
|
||||
$this->convert_rate->convert_rate($base, $target, $data, $status_code);
|
||||
return throw new Exception($data['error'] ?? 'An error occurred while processing the request, in ' . $this->config->getModuleName() . ' module');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
function sendGetRequest(string $base, string $target, string $endpoint, array $data): object
|
||||
{
|
||||
// Check if the base and target currencies are valid
|
||||
self::requireValidCurrency($base);
|
||||
self::requireValidCurrency($target);
|
||||
|
||||
// Add the base and target currencies to the data array
|
||||
$data['base'] = $base;
|
||||
|
||||
// Build the query string if any data is provided
|
||||
$query_string = '';
|
||||
if (!empty($data)) {
|
||||
$query_string = '?' . http_build_query($data);
|
||||
}
|
||||
|
||||
// Initialize cURL session
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $this->api_url . $endpoint . '/' . $query_string);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
// Set HTTP headers including the X-AUTH-TOKEN
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'X-AUTH-TOKEN: ' . $this->config->secret_key->getVariableValue(),
|
||||
]);
|
||||
|
||||
// Execute the request and handle response
|
||||
$output = curl_exec($ch);
|
||||
|
||||
// Check for errors
|
||||
if (curl_errno($ch)) {
|
||||
self::exception(
|
||||
$base,
|
||||
$target,
|
||||
[
|
||||
'method' => 'GET',
|
||||
'endpoint' => $endpoint,
|
||||
'data' => $data,
|
||||
'response' => null,
|
||||
'status_code' => 500,
|
||||
'error' => curl_error($ch),
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
// Get the status code
|
||||
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
curl_close($ch);
|
||||
// Check if the response is valid JSON
|
||||
if (!json_decode($output)) {
|
||||
$exception_message = match ($status_code) {
|
||||
401 => 'Unauthorized',
|
||||
404 => 'Not found',
|
||||
429 => 'Too many requests',
|
||||
default => 'Invalid response',
|
||||
};
|
||||
self::exception(
|
||||
$base,
|
||||
$target,
|
||||
[
|
||||
'method' => 'GET',
|
||||
'endpoint' => $endpoint,
|
||||
'data' => $data,
|
||||
'response' => null,
|
||||
'status_code' => $status_code,
|
||||
'error' => $exception_message,
|
||||
],
|
||||
$status_code
|
||||
);
|
||||
}
|
||||
return json_decode($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception If the request fails
|
||||
* @throws Exception If the response is invalid
|
||||
* @throws Exception If the response is not valid JSON
|
||||
* @throws Exception If the base or target currency is invalid
|
||||
* @throws Exception If the endpoint is invalid
|
||||
*/
|
||||
function sendPostRequest(string $base, string $target, string $endpoint, array $data): object
|
||||
{
|
||||
// Check if the base and target currencies are valid
|
||||
self::requireValidCurrency($base);
|
||||
self::requireValidCurrency($target);
|
||||
|
||||
// Initialize cURL session
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $this->api_url . $endpoint . '/' . $base . '/' . $target);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
// Set HTTP headers including the X-AUTH-TOKEN
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'X-AUTH-TOKEN: ' . $this->config->secret_key->getVariableValue(),
|
||||
]);
|
||||
|
||||
// Execute the request and handle response
|
||||
$output = curl_exec($ch);
|
||||
|
||||
// Check for errors
|
||||
if (curl_errno($ch)) {
|
||||
self::exception(
|
||||
$base,
|
||||
$target,
|
||||
[
|
||||
'method' => 'POST',
|
||||
'endpoint' => $endpoint,
|
||||
'data' => $data,
|
||||
'response' => null,
|
||||
'status_code' => 500,
|
||||
'error' => curl_error($ch),
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
// Get the status code
|
||||
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
curl_close($ch);
|
||||
// Check if the response is valid JSON
|
||||
if (!json_decode($output)) {
|
||||
self::exception(
|
||||
$base,
|
||||
$target,
|
||||
[
|
||||
'method' => 'POST',
|
||||
'endpoint' => $endpoint,
|
||||
'data' => $data,
|
||||
'response' => null,
|
||||
'status_code' => $status_code,
|
||||
'error' => 'Invalid response',
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
return json_decode($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception If the request fails
|
||||
* @throws Exception If the response is invalid
|
||||
* @throws Exception If the response is not valid JSON
|
||||
* @throws Exception If the base or target currency is invalid
|
||||
* @throws Exception If the endpoint is invalid
|
||||
*/
|
||||
function sendPutRequest(string $base, string $target, string $endpoint, array $data): object
|
||||
{
|
||||
// Check if the base and target currencies are valid
|
||||
self::requireValidCurrency($base);
|
||||
self::requireValidCurrency($target);
|
||||
|
||||
// Initialize cURL session
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $this->api_url . $endpoint . '/' . $base . '/' . $target);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
// Set HTTP headers including the X-AUTH-TOKEN
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'X-AUTH-TOKEN: ' . $this->config->secret_key->getVariableValue(),
|
||||
]);
|
||||
|
||||
// Execute the request and handle response
|
||||
$output = curl_exec($ch);
|
||||
|
||||
// Check for errors
|
||||
if (curl_errno($ch)) {
|
||||
self::exception(
|
||||
$base,
|
||||
$target,
|
||||
[
|
||||
'method' => 'PUT',
|
||||
'endpoint' => $endpoint,
|
||||
'data' => $data,
|
||||
'response' => null,
|
||||
'status_code' => 500,
|
||||
'error' => curl_error($ch),
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
// Get the status code
|
||||
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
curl_close($ch);
|
||||
// Check if the response is valid JSON
|
||||
if (!json_decode($output)) {
|
||||
self::exception(
|
||||
$base,
|
||||
$target,
|
||||
[
|
||||
'method' => 'PUT',
|
||||
'endpoint' => $endpoint,
|
||||
'data' => $data,
|
||||
'response' => null,
|
||||
'status_code' => $status_code,
|
||||
'error' => 'Invalid response',
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
return json_decode($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception If the request fails
|
||||
* @throws Exception If the response is invalid
|
||||
* @throws Exception If the response is not valid JSON
|
||||
* @throws Exception If the base or target currency is invalid
|
||||
* @throws Exception If the endpoint is invalid
|
||||
*/
|
||||
function sendDeleteRequest(string $base, string $target, string $endpoint, array $data): object
|
||||
{
|
||||
// Check if the base and target currencies are valid
|
||||
self::requireValidCurrency($base);
|
||||
self::requireValidCurrency($target);
|
||||
|
||||
// Initialize cURL session
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $this->api_url . $endpoint . '/' . $base . '/' . $target);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
// Set HTTP headers including the X-AUTH-TOKEN
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'X-AUTH-TOKEN: ' . $this->config->secret_key->getVariableValue(),
|
||||
]);
|
||||
|
||||
// Execute the request and handle response
|
||||
$output = curl_exec($ch);
|
||||
|
||||
// Check for errors
|
||||
if (curl_errno($ch)) {
|
||||
self::exception(
|
||||
$base,
|
||||
$target,
|
||||
[
|
||||
'method' => 'DELETE',
|
||||
'endpoint' => $endpoint,
|
||||
'data' => $data,
|
||||
'response' => null,
|
||||
'status_code' => 500,
|
||||
'error' => curl_error($ch),
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
// Get the status code
|
||||
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
curl_close($ch);
|
||||
// Check if the response is valid JSON
|
||||
if (!json_decode($output)) {
|
||||
self::exception(
|
||||
$base,
|
||||
$target,
|
||||
[
|
||||
'method' => 'DELETE',
|
||||
'endpoint' => $endpoint,
|
||||
'data' => $data,
|
||||
'response' => null,
|
||||
'status_code' => $status_code,
|
||||
'error' => 'Invalid response',
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
return json_decode($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
function addRequestToLog(string $base, string $target, string $endpoint, object $response): void
|
||||
{
|
||||
// Add the request to the fxratesapi request log
|
||||
$fxratesapi_lookups = new fxratesapi_conversion_rates_o();
|
||||
$fxratesapi_lookups->add($base, $target, json_encode($response), $endpoint);
|
||||
// Check if the request was added successfully
|
||||
if (!$fxratesapi_lookups->id) {
|
||||
throw new Exception('Failed to add request to log');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,7 @@ require_once 'classes/motorapi.php';
|
||||
require_once 'classes/stripe.php';
|
||||
require_once 'classes/form.php';
|
||||
require_once 'classes/pdf_generator.php';
|
||||
require_once 'classes/fxratesapi.php';
|
||||
|
||||
/**
|
||||
* Modules
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace interfaces;
|
||||
|
||||
use Exception;
|
||||
|
||||
interface fxratesapi_i
|
||||
{
|
||||
/**
|
||||
* Get conversion rate for a given base currency
|
||||
* @param string $base The base currency to use (e.g. "DKK")
|
||||
* @param string $target The target currency, e.g. "EUR")
|
||||
* @param string $endpoint The endpoint to send the request to (e.g. "latest")
|
||||
* @param array $data The data to send with the request (e.g. ["key" => "value"])
|
||||
* @return object The response from the fxratesapi
|
||||
*/
|
||||
function getConversionRate(string $base, string $target, string $endpoint, array $data): object;
|
||||
|
||||
/**
|
||||
* Get the daily request counter
|
||||
* @return int The daily request counter
|
||||
*/
|
||||
function getDailyRequestCounter(): int;
|
||||
|
||||
/**
|
||||
* Send a request to the fxratesapi
|
||||
* @param string $base The base currency to use (e.g. "DKK")
|
||||
* @param string $target The target currency, (e.g. "EUR")
|
||||
* @param string $endpoint The endpoint to send the request to (e.g. "latest")
|
||||
* @param array $data The data to send with the request (e.g. ["key" => "value"])
|
||||
* @param string $method The method to use for the request (e.g. "GET")
|
||||
* @return object The response from the fxratesapi
|
||||
*/
|
||||
function sendRequest(string $base, string $target, string $endpoint, array $data, string $method): object;
|
||||
|
||||
/**
|
||||
* Require the module to be enabled
|
||||
* @return void
|
||||
* @throws Exception If the module is not enabled
|
||||
*/
|
||||
function requireModuleEnabled(): void;
|
||||
|
||||
/**
|
||||
* Require the currency to be valid
|
||||
* @param string $currency The currency to check
|
||||
* @return void
|
||||
* @throws Exception If the currency is not valid
|
||||
*/
|
||||
function requireValidCurrency(string $currency): void;
|
||||
|
||||
/**
|
||||
* Require the daily limit to not be exceeded
|
||||
* @return void
|
||||
* @throws Exception If the daily limit is exceeded
|
||||
*/
|
||||
function requireDailyLimitNotExceeded(): void;
|
||||
|
||||
/**
|
||||
* Require the secret key to be valid
|
||||
* @return void
|
||||
* @throws Exception If the secret key is not valid
|
||||
*/
|
||||
function requireValidSecretKey(): void;
|
||||
|
||||
/**
|
||||
* Send a GET request to the fxratesapi
|
||||
* @param string $base The base currency to use (e.g. "DKK")
|
||||
* @param string $target The target currency, (e.g. "EUR")
|
||||
* @param string $endpoint The endpoint to send the request to (e.g. "latest")
|
||||
* @param array $data The data to send with the request (e.g. ["key" => "value"])
|
||||
* @return object The response from the fxratesapi
|
||||
*/
|
||||
function sendGetRequest(string $base, string $target, string $endpoint, array $data): object;
|
||||
|
||||
/**
|
||||
* Send a POST request to the fxratesapi
|
||||
* @param string $base The base currency to use (e.g. "DKK")
|
||||
* @param string $target The target currency, (e.g. "EUR")
|
||||
* @param string $endpoint The endpoint to send the request to (e.g. "latest")
|
||||
* @param array $data The data to send with the request (e.g. ["key" => "value"])
|
||||
* @return object The response from the fxratesapi
|
||||
*/
|
||||
function sendPostRequest(string $base, string $target, string $endpoint, array $data): object;
|
||||
|
||||
/**
|
||||
* Send a PUT request to the fxratesapi
|
||||
* @param string $base The base currency to use (e.g. "DKK")
|
||||
* @param string $target The target currency, (e.g. "EUR")
|
||||
* @param string $endpoint The endpoint to send the request to (e.g. "latest")
|
||||
* @param array $data The data to send with the request (e.g. ["key" => "value"])
|
||||
* @return object The response from the fxratesapi
|
||||
*/
|
||||
function sendPutRequest(string $base, string $target, string $endpoint, array $data): object;
|
||||
|
||||
/**
|
||||
* Send a DELETE request to the fxratesapi
|
||||
* @param string $base The base currency to use (e.g. "DKK")
|
||||
* @param string $target The target currency, (e.g. "EUR")
|
||||
* @param string $endpoint The endpoint to send the request to (e.g. "latest")
|
||||
* @param array $data The data to send with the request (e.g. ["key" => "value"])
|
||||
* @return object The response from the fxratesapi
|
||||
*/
|
||||
function sendDeleteRequest(string $base, string $target, string $endpoint, array $data): object;
|
||||
|
||||
/**
|
||||
* Add a request to the log
|
||||
* @param string $base The base currency to use (e.g. "DKK")
|
||||
* @param string $target The target currency, (e.g. "EUR")
|
||||
* @param string $endpoint The endpoint to send the request to
|
||||
* @param object $response The response from the fxratesapi
|
||||
* @return void
|
||||
*/
|
||||
function addRequestToLog(string $base, string $target, string $endpoint, object $response): void;
|
||||
|
||||
/**
|
||||
* Check if a conversion rate is stored in the log/local database/cache
|
||||
* @param string $base The base currency to check
|
||||
* @param string $target The target currency to check
|
||||
* @return bool Whether the conversion rate is stored in the log/local database/cache
|
||||
* @throws Exception If the base or target currency is not valid
|
||||
*/
|
||||
function isCached(string $base, string $target): bool;
|
||||
|
||||
/**
|
||||
* Cache the response for a conversion rate
|
||||
* @param string $base The base currency to cache
|
||||
* @param string $target The target currency to cache
|
||||
* @return object The cached response
|
||||
* @throws Exception If the base or target currency is not valid
|
||||
* @throws Exception If the response is not valid
|
||||
* @throws Exception If the response is not an object
|
||||
*/
|
||||
function getCachedResponse(string $base, string $target): object;
|
||||
}
|
||||
+6
-1
@@ -86,6 +86,11 @@ class economic_invoices_drafts_endpoint
|
||||
'paymentTermsNumber' => (int)$customer->getPaymentTermsNumber(),
|
||||
],
|
||||
|
||||
// Set the vat zone (This is defined in the E-conomic module settings)
|
||||
'vatZone' => [
|
||||
'vatZoneNumber' => (int)$customer->getVatZoneNumber(),
|
||||
],
|
||||
|
||||
// Set the customer number
|
||||
'customer' => [
|
||||
'customerNumber' => $customer_number
|
||||
@@ -97,7 +102,7 @@ class economic_invoices_drafts_endpoint
|
||||
],
|
||||
|
||||
// Set the currency TODO: Make this dynamic
|
||||
'currency' => 'DKK',
|
||||
'currency' => $customer->getCurrency() ?? 'DKK',
|
||||
|
||||
// Set the recipient details
|
||||
'recipient' => [
|
||||
|
||||
@@ -204,4 +204,26 @@ class economic_customer
|
||||
return $this->customer_data_object->paymentTerms->paymentTermsNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the customers currency (ISO 4217 code, e.g. DKK)
|
||||
* @return string The customers currency
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getCurrency(): string
|
||||
{
|
||||
self::requireSelected();
|
||||
return $this->customer_data_object->currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the customers VAT zone number
|
||||
* @return int The customers VAT zone number
|
||||
* @throws Exception if the customer data is invalid or empty
|
||||
*/
|
||||
public function getVatZoneNumber(): int
|
||||
{
|
||||
self::requireSelected();
|
||||
return $this->customer_data_object->vatZone->vatZoneNumber;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace fxratesapi\actions;
|
||||
|
||||
use Exception;
|
||||
use traits\module_action_t;
|
||||
|
||||
class convert_rate_a
|
||||
{
|
||||
use module_action_t;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception If the module name is invalid
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
self::set_module_name('FXRATESAPI');
|
||||
|
||||
/** Add the action to the list of valid actions */
|
||||
// Convert rate action
|
||||
self::add_action(
|
||||
'CONVERT_RATE',
|
||||
'This action is when a currency conversion is requested',
|
||||
// Method to call
|
||||
self::class . '::convert_rate',
|
||||
[
|
||||
'from' => 'The currency to convert from (ISO 4217)',
|
||||
'to' => 'The currency to convert to (ISO 4217)',
|
||||
'data' => 'The data returned from the conversion (If any)',
|
||||
'status_code' => 'The status code of the action',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert rate action
|
||||
* @param string $from The currency to convert from (ISO 4217)
|
||||
* @param string $to The currency to convert to (ISO 4217)
|
||||
* @param array|object $data The data returned from the conversion (If any)
|
||||
* @param int $status_code The status code of the action
|
||||
* @throws Exception If the action name is invalid
|
||||
* @throws Exception If the action data is invalid
|
||||
* @throws Exception If the action status code is invalid
|
||||
* @throws Exception If the action is not valid
|
||||
*/
|
||||
public function convert_rate(string $from, string $to, array|object $data = [], int $status_code = 0): void
|
||||
{
|
||||
self::set_action('CONVERT_RATE');
|
||||
// If the data is an object, convert it to an array
|
||||
if (is_object($data)) {
|
||||
$data = (array)$data;
|
||||
}
|
||||
// Validate the action data
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Action data is invalid');
|
||||
}
|
||||
// Validate the action status code
|
||||
self::set_data([
|
||||
'from' => $from,
|
||||
'to' => $to,
|
||||
'data' => $data,
|
||||
]);
|
||||
self::set_status($status_code);
|
||||
// Add the action to the log
|
||||
self::add_action_log(
|
||||
self::get_action_name(),
|
||||
(int)self::get_status(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace fxratesapi\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class fxratesapi_daily_limit_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'fxratesapi',
|
||||
'daily_limit',
|
||||
'int',
|
||||
true,
|
||||
null,
|
||||
'The API request limit for the fxratesapi module',
|
||||
'1',
|
||||
false,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace fxratesapi\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class fxratesapi_enabled_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'fxratesapi',
|
||||
'enabled',
|
||||
'bool',
|
||||
true,
|
||||
null,
|
||||
'Whether the fxratesapi module is enabled or not',
|
||||
'1',
|
||||
false,
|
||||
'false'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace fxratesapi\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class fxratesapi_secret_key_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'fxratesapi',
|
||||
'secret_key',
|
||||
'string',
|
||||
false,
|
||||
null,
|
||||
'The API token for fxratesapi.com',
|
||||
'1',
|
||||
true,
|
||||
''
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace fxratesapi;
|
||||
require_once WD . '/modules/fxratesapi/config/fxratesapi_enabled_c.php';
|
||||
require_once WD . '/modules/fxratesapi/config/fxratesapi_secret_key_c.php';
|
||||
require_once WD . '/modules/fxratesapi/config/fxratesapi_daily_limit_c.php';
|
||||
|
||||
use fxratesapi\config\fxratesapi_daily_limit_c;
|
||||
use fxratesapi\config\fxratesapi_enabled_c;
|
||||
use fxratesapi\config\fxratesapi_secret_key_c;
|
||||
use traits\module_config_t;
|
||||
|
||||
class fxratesapi_c
|
||||
{
|
||||
use module_config_t;
|
||||
|
||||
/**
|
||||
* The status of the fxratesapi module
|
||||
* @var fxratesapi_enabled_c
|
||||
*/
|
||||
public fxratesapi_enabled_c $enabled;
|
||||
/**
|
||||
* The secret key for the fxratesapi module (API token)
|
||||
* @var fxratesapi_secret_key_c
|
||||
*/
|
||||
public fxratesapi_secret_key_c $secret_key;
|
||||
/**
|
||||
* The daily limit for the fxratesapi module
|
||||
* @var fxratesapi_daily_limit_c
|
||||
*/
|
||||
public fxratesapi_daily_limit_c $daily_limit;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setupConfig('fxratesapi');
|
||||
$this->allowUpdate([
|
||||
fxratesapi_enabled_c::class,
|
||||
fxratesapi_secret_key_c::class,
|
||||
fxratesapi_daily_limit_c::class
|
||||
]);
|
||||
$this->enabled = new fxratesapi_enabled_c();
|
||||
$this->secret_key = new fxratesapi_secret_key_c();
|
||||
$this->daily_limit = new fxratesapi_daily_limit_c();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace objects;
|
||||
|
||||
use classes\db;
|
||||
use classes\object_property;
|
||||
use Exception;
|
||||
use traits\db_object_t;
|
||||
|
||||
class currency_conversion_rates_o extends db
|
||||
{
|
||||
use db_object_t;
|
||||
|
||||
public object_property $currency;
|
||||
public object_property $rate;
|
||||
public object_property $updated_at;
|
||||
public object_property $created_at;
|
||||
|
||||
|
||||
public function structure(): void
|
||||
{
|
||||
$this->setTable('currency_conversion_rates');
|
||||
}
|
||||
|
||||
public function asArray(): array
|
||||
{
|
||||
return [
|
||||
'id' => (int)$this->id,
|
||||
'currency' => (string)$this->currency->value(),
|
||||
'rate' => (float)$this->rate->value(),
|
||||
'updated_at' => (string)$this->updated_at->value(),
|
||||
'created_at' => (string)$this->created_at->value(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update (or create) the conversion rates
|
||||
* @param object $currencies The currencies to update (e.g. { "DKK": 1.0, "EUR": 0.5 })
|
||||
* @return void
|
||||
* @throws Exception If the currency is not valid
|
||||
* @throws Exception If the rate is not valid
|
||||
*/
|
||||
public function setMany(object $currencies): void
|
||||
{
|
||||
// Check if the currencies are valid
|
||||
if (!is_object($currencies)) {
|
||||
throw new Exception('The currencies are not valid.');
|
||||
}
|
||||
// Check if the currencies are empty
|
||||
if (empty($currencies)) {
|
||||
throw new Exception('The currencies are empty.');
|
||||
}
|
||||
// Transform the object to an array
|
||||
$currencies = (array)$currencies;
|
||||
foreach ( $currencies as $currency => $relative_rate ) {
|
||||
// Check if the currency is valid
|
||||
if (!self::validateCurrencyFormat($currency)) {
|
||||
throw new Exception('The currency is not valid. (' . $currency . ')');
|
||||
}
|
||||
// Check if the rate is valid
|
||||
if ($relative_rate <= 0) {
|
||||
throw new Exception('The rate is not valid.');
|
||||
}
|
||||
// Update the conversion rate
|
||||
self::set($currency, $relative_rate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the format of a currency
|
||||
* @note This simply checks if the currency is in the format of up to three uppercase letters.
|
||||
* @note This does not check if the currency is actually valid.
|
||||
* @param string $currency
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateCurrencyFormat(string $currency): bool
|
||||
{
|
||||
return (bool)preg_match('/^[A-Z]{1,3}$/', $currency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update (or create) the conversion rate for a currency
|
||||
* @param string $currency The currency to update (e.g. "DKK")
|
||||
* @param float $relative_rate The conversion rate to update (e.g. 1.0)
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function set(string $currency, float $relative_rate): void
|
||||
{
|
||||
global /** @var db $db */
|
||||
$db;
|
||||
// Check if the object exists
|
||||
if (!self::countRowsWhere(['currency' => $currency])) {
|
||||
// If not, add it
|
||||
self::add($currency, $relative_rate);
|
||||
return;
|
||||
}
|
||||
// If it does, update it
|
||||
// Get the object
|
||||
$result = self::getFieldsWhere(['currency' => $currency], ['id']);
|
||||
if (empty($result)) {
|
||||
throw new Exception('The currency conversion rate does exist, but the id was not found.');
|
||||
}
|
||||
self::select((int)$result[0]['id']);
|
||||
// Update the object
|
||||
$this->rate->set((float)$relative_rate);
|
||||
self::objectChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new object to the database
|
||||
* @param string $currency The currency to update (e.g. "DKK")
|
||||
* @param float $relative_rate The conversion rate to update (e.g. 1.0)
|
||||
* @return currency_conversion_rates_o
|
||||
* @throws Exception If the object was not created successfully
|
||||
*/
|
||||
public function add(string $currency, float $relative_rate): self
|
||||
{
|
||||
global /** @var db $db */
|
||||
$db;
|
||||
// Sanitize the input
|
||||
$currency = $db->escape_string($currency);
|
||||
$relative_rate = (float)$relative_rate;
|
||||
// Check if the currency is valid
|
||||
if (!self::validateCurrencyFormat($currency)) {
|
||||
throw new Exception('The currency is not valid.');
|
||||
}
|
||||
// Check if the rate is valid
|
||||
if ($relative_rate <= 0) {
|
||||
throw new Exception('The rate is not valid.');
|
||||
}
|
||||
// Add the object
|
||||
$tmp_id = self::add_object([
|
||||
'currency' => $currency,
|
||||
'rate' => $relative_rate,
|
||||
]);
|
||||
$this->id = $tmp_id;
|
||||
self::getObjectProperties();
|
||||
self::objectChanged();
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getObjectProperties(): void
|
||||
{
|
||||
$this->currency = new object_property($this->table, $this->id, 'currency', 'string', false);
|
||||
$this->rate = new object_property($this->table, $this->id, 'rate', 'float', false);
|
||||
$this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'datetime', false);
|
||||
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'datetime', false);
|
||||
}
|
||||
|
||||
public function objectChanged(): void
|
||||
{
|
||||
//TODO: Add cache invalidation
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
namespace objects;
|
||||
|
||||
use classes\db;
|
||||
use classes\object_property;
|
||||
use Exception;
|
||||
use traits\db_object_t;
|
||||
|
||||
class fxratesapi_conversion_rates_o extends db
|
||||
{
|
||||
use db_object_t;
|
||||
|
||||
public object_property $base;
|
||||
public object_property $target;
|
||||
public object_property $result;
|
||||
public object_property $endpoint;
|
||||
public object_property $created_at;
|
||||
|
||||
|
||||
public function structure(): void
|
||||
{
|
||||
$this->setTable('fxratesapi_conversion_rates');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new object to the database
|
||||
* @param string $base The base currency to use (e.g. "DKK")
|
||||
* @param string $target The target currency, (e.g. "EUR")
|
||||
* @param string $result
|
||||
* @param string $endpoint
|
||||
* @return void
|
||||
* @throws Exception If the object was not created successfully
|
||||
*/
|
||||
public function add(string $base, string $target, string $result, string $endpoint): void
|
||||
{
|
||||
global /** @var db $db */
|
||||
$db;
|
||||
// Sanitize the input
|
||||
$base = $db->escape_string($base);
|
||||
$target = $db->escape_string($target);
|
||||
$result = $db->escape_string($result);
|
||||
$endpoint = $db->escape_string($endpoint);
|
||||
// Add the object
|
||||
$tmp_id = self::add_object([
|
||||
'base' => $base,
|
||||
'target' => $target,
|
||||
'result' => $result,
|
||||
'endpoint' => $endpoint
|
||||
]);
|
||||
$this->id = $tmp_id;
|
||||
self::getObjectProperties();
|
||||
self::objectChanged();
|
||||
}
|
||||
|
||||
public function getObjectProperties(): void
|
||||
{
|
||||
$this->base = new object_property($this->table, $this->id, 'base', 'string', false);
|
||||
$this->target = new object_property($this->table, $this->id, 'target', 'string', false);
|
||||
$this->result = new object_property($this->table, $this->id, 'result', 'string', false);
|
||||
$this->endpoint = new object_property($this->table, $this->id, 'endpoint', 'string', false);
|
||||
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'datetime', false);
|
||||
}
|
||||
|
||||
public function objectChanged(): void
|
||||
{
|
||||
//TODO: Add cache invalidation
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of requests made today
|
||||
* @return int
|
||||
*/
|
||||
public function getTodayCount(): int
|
||||
{
|
||||
global /** @var db $db */
|
||||
$db;
|
||||
$sql = 'SELECT COUNT(*) FROM ' . $this->table . ' WHERE DATE(created_at) = CURDATE()';
|
||||
$result = $db->query($sql);
|
||||
return (int)$result->fetch_row()[0];
|
||||
}
|
||||
|
||||
public function asArray(): array
|
||||
{
|
||||
return [
|
||||
'id' => (int)$this->id,
|
||||
'base' => (string)$this->base->value(),
|
||||
'target' => (string)$this->target->value(),
|
||||
'result' => (string)$this->result->value(),
|
||||
'endpoint' => (string)$this->endpoint->value(),
|
||||
'created_at' => (string)$this->created_at->value(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the conversion rate cached within the last 10 minutes?
|
||||
* @param string $base The base currency to check
|
||||
* @param string $target The target currency to check
|
||||
* @return bool
|
||||
* @throws Exception If the base or target currency is not valid
|
||||
*/
|
||||
public function isCached(string $base, string $target): bool
|
||||
{
|
||||
global /** @var db $db */
|
||||
$db;
|
||||
if (!self::validateCurrencyFormat($base) || !self::validateCurrencyFormat($target)) {
|
||||
throw new Exception('The base or target currency is not valid.');
|
||||
}
|
||||
$sql = 'SELECT COUNT(*) FROM ' . $this->table . ' WHERE base = "' . $db->escape_string($base) . '" AND target = "' . $db->escape_string($target) . '" AND created_at > DATE_SUB(NOW(), INTERVAL 10 MINUTE)';
|
||||
$result = $db->query($sql);
|
||||
return (bool)$result->fetch_row()[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the format of a currency
|
||||
* @note This simply checks if the currency is in the format of three uppercase letters.
|
||||
* @note This does not check if the currency is actually valid.
|
||||
* @param string $currency
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateCurrencyFormat(string $currency): bool
|
||||
{
|
||||
return (bool)preg_match('/^[A-Z]{3}$/', $currency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the (latest) cached result for a conversion rate
|
||||
* @param string $base The base currency to check
|
||||
* @param string $target The target currency to check
|
||||
* @return object
|
||||
* @throws Exception If the base or target currency is not valid or the response is not cached
|
||||
*/
|
||||
public function getCachedResult(string $base, string $target): object
|
||||
{
|
||||
global /** @var db $db */
|
||||
$db;
|
||||
if (!self::validateCurrencyFormat($base) || !self::validateCurrencyFormat($target)) {
|
||||
throw new Exception('The base or target currency is not valid.');
|
||||
}
|
||||
$result = self::getFieldsWhere(['base' => $base, 'target' => $target], ['id', 'result', 'endpoint', 'created_at']);
|
||||
if (!$result) {
|
||||
throw new Exception('The response is not cached.');
|
||||
}
|
||||
// Get the latest result
|
||||
$latest = array_pop($result);
|
||||
$this->id = $latest['id'];
|
||||
self::getObjectProperties();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the (latest) cached response for a conversion rate
|
||||
* @param string $base The base currency to check
|
||||
* @param string $target The target currency to check
|
||||
* @return object
|
||||
* @throws Exception If the base or target currency is not valid or the response is not cached
|
||||
* @note This is a wrapper for getCachedResult
|
||||
*/
|
||||
public function getCachedResponse(string $base, string $target): object
|
||||
{
|
||||
global /** @var db $db */
|
||||
$db;
|
||||
if (!self::validateCurrencyFormat($base) || !self::validateCurrencyFormat($target)) {
|
||||
throw new Exception('The base or target currency is not valid.');
|
||||
}
|
||||
$result = self::getFieldsWhere(['base' => $base, 'target' => $target], ['id', 'result', 'endpoint', 'created_at']);
|
||||
if (!$result) {
|
||||
throw new Exception('The response is not cached.');
|
||||
}
|
||||
// Get the latest result
|
||||
$latest = array_pop($result);
|
||||
$this->id = $latest['id'];
|
||||
self::getObjectProperties();
|
||||
return json_decode($latest['result']);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ use classes\authentication;
|
||||
use classes\backup_store;
|
||||
use classes\economic;
|
||||
use classes\email;
|
||||
use classes\fxratesapi;
|
||||
use classes\motorapi;
|
||||
use classes\recaptcha;
|
||||
use classes\response;
|
||||
@@ -293,5 +294,44 @@ class moduleConfigRoute
|
||||
'stripe_config' => 'Update stripe config'
|
||||
]
|
||||
);
|
||||
|
||||
/** FXRatesAPI config > GET */
|
||||
$this->get('/fxratesapi/config', function () {
|
||||
global $response;
|
||||
$this->requirePermission('fxratesapi_config');
|
||||
$user = (new authentication())->get_user();
|
||||
if ($user) {
|
||||
(new logs_o())->add('fxratesapi_config', 'global', 1, $user->id, 'FXRATESAPI_CONFIG', 'Successfully fetched fxratesapi config');
|
||||
$response->success(
|
||||
(new fxratesapi())->config->getConfigRequest()
|
||||
);
|
||||
} else {
|
||||
(new logs_o())->add('fxratesapi_config', 'global', 1, 0, 'FXRATESAPI_CONFIG', 'No user found, or invalid session');
|
||||
$response->error('Invalid session', 400);
|
||||
}
|
||||
},
|
||||
[
|
||||
'fxratesapi_config' => 'Get fxratesapi config'
|
||||
]
|
||||
);
|
||||
/** FXRatesAPI config > POST */
|
||||
$this->post('/fxratesapi/config', function () {
|
||||
global $response;
|
||||
$this->requirePermission('fxratesapi_config');
|
||||
$user = (new authentication())->get_user();
|
||||
if ($user) {
|
||||
(new logs_o())->add('fxratesapi_config', 'global', 1, $user->id, 'FXRATESAPI_CONFIG', 'Successfully updated fxratesapi config');
|
||||
$response->success(
|
||||
(new fxratesapi())->config->postConfigRequest()
|
||||
);
|
||||
} else {
|
||||
(new logs_o())->add('fxratesapi_config', 'global', 1, 0, 'FXRATESAPI_CONFIG', 'No user found, or invalid session');
|
||||
$response->error('Invalid session', 400);
|
||||
}
|
||||
},
|
||||
[
|
||||
'fxratesapi_config' => 'Update fxratesapi config'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace routes;
|
||||
|
||||
use classes\authentication;
|
||||
use classes\fxratesapi;
|
||||
use classes\response;
|
||||
use classes\router;
|
||||
use objects\currency_conversion_rates_o;
|
||||
use objects\logs_o;
|
||||
use traits\route_t;
|
||||
|
||||
class moduleFxRatesAPIRoute
|
||||
{
|
||||
use route_t;
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
global /** @var response $response */
|
||||
/** @var router $router */
|
||||
$router, $response;
|
||||
|
||||
|
||||
/** Modules > FXRatesAPI > conversion rate > GET */
|
||||
$this->get('/modules/fxratesapi/rate', function () {
|
||||
global $response;
|
||||
self::requirePermission('modules_fxratesapi_rate');
|
||||
$user = (new authentication())->get_user();
|
||||
if ($user) {
|
||||
self::requireParameters(['base', 'target']);
|
||||
self::requireType('base', self::type_string());
|
||||
self::requireType('target', self::type_string());
|
||||
self::requireMinLength('base', 3);
|
||||
self::requireMaxLength('base', 3);
|
||||
self::requireMinLength('target', 3);
|
||||
self::requireMaxLength('target', 3);
|
||||
(new logs_o())->add('modules_fxratesapi', 'global', 1, $user->id, 'MODULES_FXRATESAPI', 'User accessed the conversion rate');
|
||||
$result = (new fxratesapi())->getConversionRate(
|
||||
self::getParameter('base'),
|
||||
self::getParameter('target'),
|
||||
'latest',
|
||||
[]
|
||||
);
|
||||
// Check if the result is an error
|
||||
if (!isset($result->success) || !$result->success) {
|
||||
(new logs_o())->add('modules_fxratesapi', 'global', 1, $user->id, 'MODULES_FXRATESAPI', 'User accessed the conversion rate and got an error');
|
||||
$response->error($result->error, 400);
|
||||
}
|
||||
// Set the rates
|
||||
$currency_conversion_rates = (new currency_conversion_rates_o());
|
||||
$currency_conversion_rates->setMany($result->rates);
|
||||
// Response
|
||||
$response->success($result->rates, 200);
|
||||
} else {
|
||||
(new logs_o())->add('modules_fxratesapi', 'global', 1, 0, 'MODULES_FXRATESAPI', 'User accessed the conversion rate without being logged in');
|
||||
$response->error('Invalid session', 400);
|
||||
}
|
||||
},
|
||||
[
|
||||
'modules_fxratesapi_rate' => 'Get conversion rate',
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user