diff --git a/lib/Service/FetchCurrenciesService.php b/lib/Service/FetchCurrenciesService.php index 6a34fcb..eb87004 100644 --- a/lib/Service/FetchCurrenciesService.php +++ b/lib/Service/FetchCurrenciesService.php @@ -21,6 +21,7 @@ use OCA\AutoCurrency\Db\CustomCurrency; use OCA\AutoCurrency\Db\CustomCurrencyMapper; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; +use OCP\Http\Client\IClientService; use OCP\IAppConfig; use Psr\Log\LoggerInterface; @@ -60,6 +61,7 @@ class FetchCurrenciesService { private CospendProjectMapper $projectMapper, private AutocurrencyRateHistoryMapper $historyMapper, private CustomCurrencyMapper $customCurrencyMapper, + private IClientService $clientService, private LoggerInterface $logger, ) { $this->config = $config; @@ -67,6 +69,7 @@ class FetchCurrenciesService { $this->projectMapper = $projectMapper; $this->historyMapper = $historyMapper; $this->customCurrencyMapper = $customCurrencyMapper; + $this->clientService = $clientService; $this->logger = $logger; $this->loadSymbols(); } @@ -189,23 +192,18 @@ class FetchCurrenciesService { $this->logger->info('Fetching exchange rates for base currency ' . $baseCurrency); $url = $this->replaceTokens(self::$EXCHANGE_URL, $baseCurrency); - $fp = @fopen($url, 'r'); - if (!$fp) { - $err = error_get_last(); - throw new \RuntimeException("Failed to open URL: $url — " . ($err['message'] ?? 'unknown error')); - } + $client = $this->clientService->newClient(); + $response = $client->get($url); + $data = $response->getBody(); - $data = stream_get_contents($fp); - fclose($fp); - - if ($data === false || $data === '') { - throw new \RuntimeException("Empty response from URL: $url"); + if ($data === '') { + throw new \RuntimeException("Empty response from URL: $url (HTTP " . $response->getStatusCode() . ')'); } $json = json_decode($data, true); if ($json === null) { - throw new \RuntimeException("Invalid JSON from $url (first 200 chars): " . substr($data, 0, 200)); + throw new \RuntimeException("Invalid JSON from $url (HTTP " . $response->getStatusCode() . ', first 200 chars): ' . substr($data, 0, 200)); } if (!isset($json[$baseCurrency])) { @@ -322,37 +320,24 @@ class FetchCurrenciesService { $this->logger->debug("Fetching API response from: $url"); - // Set up stream context with headers if API key is provided - $opts = [ - 'http' => [ - 'method' => 'GET', - 'header' => '', - ], - ]; - + $options = []; if ($apiKey && $apiKey !== '') { - $opts['http']['header'] = "Authorization: Bearer $apiKey\r\n"; + $options['headers'] = ['Authorization' => "Bearer $apiKey"]; $this->logger->debug('Using API key for authentication'); } - $context = stream_context_create($opts); - $fp = @fopen($url, 'r', false, $context); - if (!$fp) { - $err = error_get_last(); - throw new \RuntimeException("Failed to open URL: $url — " . ($err['message'] ?? 'unknown error')); - } + $client = $this->clientService->newClient(); + $response = $client->get($url, $options); + $data = $response->getBody(); - $data = stream_get_contents($fp); - fclose($fp); - - if ($data === false || $data === '') { - throw new \RuntimeException("Empty response from URL: $url"); + if ($data === '') { + throw new \RuntimeException("Empty response from URL: $url (HTTP " . $response->getStatusCode() . ')'); } $json = json_decode($data, true); if ($json === null) { - throw new \RuntimeException("Failed to decode JSON from $url (first 200 chars): " . substr($data, 0, 200)); + throw new \RuntimeException("Failed to decode JSON from $url (HTTP " . $response->getStatusCode() . ', first 200 chars): ' . substr($data, 0, 200)); } $this->apiCache[$cacheKey] = $json; diff --git a/tests/unit/Controller/ApiControllerTest.php b/tests/unit/Controller/ApiControllerTest.php index eac8bb2..0757c56 100644 --- a/tests/unit/Controller/ApiControllerTest.php +++ b/tests/unit/Controller/ApiControllerTest.php @@ -40,6 +40,7 @@ use OCA\AutoCurrency\Db\CustomCurrency; use OCA\AutoCurrency\Db\CustomCurrencyMapper; use OCA\AutoCurrency\Service\FetchCurrenciesService; use OCA\Cospend\Db\Project; +use OCP\Http\Client\IClientService; use OCP\IAppConfig; use OCP\IL10N; use OCP\IRequest; @@ -87,10 +88,11 @@ final class ApiControllerTest extends TestCase { $this->logger = $opts['logger'] ?? $this->createMock(LoggerInterface::class); $this->customCurrencyMapper->method('findAll')->willReturn([]); + $clientService = $this->createMock(IClientService::class); if (!empty($opts['serviceMethods'])) { $this->service = $this->getMockBuilder(FetchCurrenciesService::class) - ->setConstructorArgs([$this->config, $this->currencyMapper, $this->projectMapper, $this->historyMapper, $this->customCurrencyMapper, $this->logger]) + ->setConstructorArgs([$this->config, $this->currencyMapper, $this->projectMapper, $this->historyMapper, $this->customCurrencyMapper, $clientService, $this->logger]) ->onlyMethods($opts['serviceMethods']) ->getMock(); } else { @@ -100,6 +102,7 @@ final class ApiControllerTest extends TestCase { $this->projectMapper, $this->historyMapper, $this->customCurrencyMapper, + $clientService, $this->logger ); } diff --git a/tests/unit/Service/FetchCurrenciesServiceTest.php b/tests/unit/Service/FetchCurrenciesServiceTest.php index 3673264..37dedab 100644 --- a/tests/unit/Service/FetchCurrenciesServiceTest.php +++ b/tests/unit/Service/FetchCurrenciesServiceTest.php @@ -13,6 +13,7 @@ use OCA\AutoCurrency\Db\CurrencyMapper; use OCA\AutoCurrency\Db\CustomCurrency; use OCA\AutoCurrency\Db\CustomCurrencyMapper; use OCA\AutoCurrency\Service\FetchCurrenciesService; +use OCP\Http\Client\IClientService; use OCP\IAppConfig; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -27,6 +28,7 @@ final class FetchCurrenciesServiceTest extends TestCase { $projectMapper = $this->createMock(CospendProjectMapper::class); $historyMapper = $this->createMock(AutocurrencyRateHistoryMapper::class); $customCurrencyMapper = $this->createMock(CustomCurrencyMapper::class); + $clientService = $this->createMock(IClientService::class); $logger = $this->createMock(LoggerInterface::class); $customCurrencyMapper->method('findAll')->willReturn([]); @@ -37,6 +39,7 @@ final class FetchCurrenciesServiceTest extends TestCase { $projectMapper, $historyMapper, $customCurrencyMapper, + $clientService, $logger );