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 } /** * Convert an amount from the base currency to the target currency * @param string $currency The target currency (e.g. "EUR") * @param float $amount The amount to convert in the base currency (e.g. 100) which is 100 DKK * @throws Exception */ public function convertTo(string $currency, float $amount): float { // Check if the currency is valid if (!self::validateCurrencyFormat($currency)) { throw new Exception('The currency is not valid.'); } // Check if the amount is valid if ($amount <= 0) { throw new Exception('The amount is not valid.'); } // Convert the amount return self::getRate($currency) * $amount; } /** * Get the conversion rate for a currency * @param string $currency The currency to get (e.g. "DKK") * @return float The conversion rate (e.g. 1.0) * @throws Exception If the currency is not valid */ public function getRate(string $currency): float { // Check if the currency is valid if (!self::validateCurrencyFormat($currency)) { throw new Exception('The currency is not valid.'); } // Check if the currency is 'DKK', then return 1.0 (base currency) if ($currency === 'DKK') { return 1.0; } // Get the conversion rate $result = self::getFieldsWhere(['currency' => $currency], ['rate']); if (empty($result)) { throw new Exception('The currency conversion rate does not exist.'); } return (float)$result[0]['rate']; } }