Refactor exchange rate providers into driver-based architecture

Replace duplicated switch/case blocks across 4 methods with a clean
abstract driver pattern:

- ExchangeRateDriver (abstract): defines getExchangeRate(),
  getSupportedCurrencies(), validateConnection()
- CurrencyFreakDriver, CurrencyLayerDriver, OpenExchangeRateDriver,
  CurrencyConverterDriver: concrete implementations
- ExchangeRateDriverFactory: resolves driver name to class, with
  register() method for module extensibility

Delete ExchangeRateProvidersTrait — all logic now lives in driver
classes and ExchangeRateProviderService. Adding a new exchange rate
provider only requires implementing ExchangeRateDriver and calling
ExchangeRateDriverFactory::register() in a module service provider.
This commit is contained in:
Darko Gjorgjijoski
2026-04-03 20:24:03 +02:00
parent 8f29e8f5de
commit 85b62dfdf8
10 changed files with 354 additions and 280 deletions

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Services\ExchangeRate;
use InvalidArgumentException;
class ExchangeRateDriverFactory
{
/** @var array<string, class-string<ExchangeRateDriver>> */
protected static array $drivers = [
'currency_freak' => CurrencyFreakDriver::class,
'currency_layer' => CurrencyLayerDriver::class,
'open_exchange_rate' => OpenExchangeRateDriver::class,
'currency_converter' => CurrencyConverterDriver::class,
];
/**
* Register a custom exchange rate driver (for module extensibility).
*/
public static function register(string $name, string $driverClass): void
{
static::$drivers[$name] = $driverClass;
}
public static function make(string $driver, string $apiKey, array $config = []): ExchangeRateDriver
{
$class = static::$drivers[$driver] ?? null;
if (! $class) {
throw new InvalidArgumentException("Unknown exchange rate driver: {$driver}");
}
return new $class($apiKey, $config);
}
/**
* Get all registered driver names.
*/
public static function availableDrivers(): array
{
return array_keys(static::$drivers);
}
}