Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
50.00% |
2 / 4 |
CRAP | |
83.87% |
26 / 31 |
| SampleDataSource | |
0.00% |
0 / 1 |
|
50.00% |
2 / 4 |
10.42 | |
83.87% |
26 / 31 |
| __construct | |
100.00% |
1 / 1 |
3 | |
100.00% |
13 / 13 |
|||
| getQuotes | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| transformResponseInQuotesCollection | |
0.00% |
0 / 1 |
3.21 | |
71.43% |
5 / 7 |
|||
| fetchQuotesFromSource | |
0.00% |
0 / 1 |
3.24 | |
70.00% |
7 / 10 |
|||
| <?php | |
| declare(strict_types=1); | |
| namespace App\Quote\DataSource; | |
| use App\Quote\Collection\QuoteCollection; | |
| use App\Quote\Collection\QuoteCollectionInterface; | |
| use App\Quote\DataSource\Exception\DataSourceException; | |
| use App\Quote\DataSource\Exception\DataSourceIsNotReadableException; | |
| use Psr\Log\LoggerInterface; | |
| use Symfony\Component\Cache\Adapter\AdapterInterface; | |
| use Symfony\Component\HttpClient\Exception\ClientException; | |
| use Symfony\Component\HttpFoundation\Request; | |
| use Symfony\Component\HttpFoundation\Response; | |
| use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; | |
| use Symfony\Contracts\HttpClient\HttpClientInterface; | |
| use Symfony\Contracts\HttpClient\ResponseInterface; | |
| use Webmozart\Assert\Assert; | |
| final class SampleDataSource implements DataSourceInterface | |
| { | |
| private const KEY = 'SampleDataSource'; | |
| private HttpClientInterface $httpClient; | |
| private QuoteCollectionInterface $quotes; | |
| private AdapterInterface $cache; | |
| private LoggerInterface $logger; | |
| private string $url; | |
| public function __construct( | |
| HttpClientInterface $httpClient, | |
| AdapterInterface $cache, | |
| LoggerInterface $logger, | |
| string $dataSourceUrl | |
| ) { | |
| $this->httpClient = $httpClient; | |
| $this->cache = $cache; | |
| $this->url = $dataSourceUrl; | |
| $this->logger = $logger; | |
| $cachedItem = $this->cache->getItem(self::KEY); | |
| if ($cachedItem->get() instanceof QuoteCollectionInterface) { | |
| $this->quotes = $cachedItem->get(); | |
| $this->logger->info('Data fetched from cache', ['DataSource' => self::KEY]); | |
| } | |
| if (false === $cachedItem->isHit()) { | |
| $this->fetchQuotesFromSource(); | |
| $cachedItem->set($this->quotes); | |
| $this->cache->save($cachedItem); | |
| } | |
| } | |
| public function getQuotes(): QuoteCollectionInterface | |
| { | |
| return $this->quotes; | |
| } | |
| private function transformResponseInQuotesCollection(ResponseInterface $rawDataResponse): array | |
| { | |
| if ($rawDataResponse->getStatusCode() !== Response::HTTP_OK) { | |
| return []; | |
| } | |
| $data = json_decode($rawDataResponse->getContent(), true, 512, JSON_THROW_ON_ERROR); | |
| if (empty($data)) { | |
| return []; | |
| } | |
| Assert::keyExists($data, 'quotes'); | |
| return $data['quotes']; | |
| } | |
| private function fetchQuotesFromSource(): void | |
| { | |
| try { | |
| $rawDataResponse = $this->httpClient->request(Request::METHOD_GET, $this->url); | |
| } catch (TransportExceptionInterface | ClientException $e) { | |
| throw new DataSourceException( | |
| sprintf('Could not fetch quotes from %s data source', __CLASS__) | |
| ); | |
| } | |
| if ($rawDataResponse->getStatusCode() === Response::HTTP_NOT_FOUND) { | |
| throw new DataSourceIsNotReadableException( | |
| sprintf('The url %s provided is not readable or reachable', $this->url) | |
| ); | |
| } | |
| $this->logger->info('Raw data fetched from text collection quotes api', ['DataSource' => self::KEY]); | |
| $this->quotes = QuoteCollection::fromArray($this->transformResponseInQuotesCollection($rawDataResponse)); | |
| } | |
| } |