---
# System prepended metadata

title: Untitled

---

```
<?php

namespace src\Integration;

use src\Integlration\APIException;

class DataProvider
{
    /**
     * @var string
     */
    private $host;
    
    /**
     * @var string
     */
    private $user;
    
    /**
     * @var string
     */
    private $password;

    /**
     * @param string $host
     * @param string $user
     * @param string $password
     */
    public function __construct($host, $user, $password)
    {
        $this->host = $host;
        $this->user = $user;
        $this->password = $password;
    }

    /**
     * @param array $request
     * @return array
     * @throws APIException
     */
    public function get(array $request)
    {
        // returns a response from external service
    }
}
```

```
<?php

namespace src\Data;

use Exception;
use Library\HttpLibraryException;
use Psr\Log\LoggerInterface;
use src\Cache\Cache;
use src\Cache\CacheException;
use src\Integlration\APIException;
use src\Integration\DataProvider;

class DataManager
{
    /**
     * @var DataProvider
     */
    private $dataProvider;
    
    /**
     * @var Cache
     */
    private $cache;
    
    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @param DataProvider $dataProvider
     * @param Cache $cache
     * @param LoggerInterface $logger
     */
    public function __construct(DataProvider $dataProvider, Cache $cache, LoggerInterface $logger)
    {
        $this->dataProvider = $dataProvider;
        $this->cache = $cache;
        $this->logger = $logger;
    }

    /**
     * @param array $input
     * @return array
     * @throws CacheException
     */
    public function getResponse(array $input)
    {
        $result = null;
        $cacheKey = $this->cache->getCacheKey(json_encode($input));
        try {
            $result = $this->dataProvider->get($input);
            $this->checkResult($result);

            $this->cache->set($cacheKey, $result);
        } catch (CacheException $cacheException) {
            $this->logger->critical(
                $cacheException->getMessage(),
                $this->getErrorLogContext($input, $result, $cacheException)
            );
        } catch (APIException | HttpLibraryException | InvalidResponseDataException | Exception $exception) {
            $this->logger->error(
                $exception->getMessage(),
                $this->getErrorLogContext($input, $result, $exception)
            );
        }

        if ($result === null) {
            $result = $this->cache->get($cacheKey) ?: [];
        }

        return $result;
    }

    /**
     * @param mixed $result
     * @throws InvalidResponseDataException
     */
    private function checkResult($result)
    {
        // check response data with some json schema and other invalid or dangerous data

        if (/** not valid */) {
            throw new InvalidResponseDataException(/** message which data is invalid */);
        }
    }

    /**
     * @param array $input
     * @param array|null $result
     * @param Exception $exception
     * @return array
     */
    private function getErrorLogContext($input, $result, Exception $exception)
    {
        $logContext = [
            'request' => $input,
            'response' => $result,
            'exception' => $exception,
        ];

        if ($exception instanceof APIException) {
            $logContext['http_code'] = $exception->getHttpCode();
            $logContext['response_body'] = $exception->getResponseBody();
        }

        return $logContext;
    }
}
```

```
<?php

namespace src\Cache;

use DateTime;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;

class Cache
{
    /**
     * @var CacheItemPoolInterface
     */
    private $cache;

    /**
     * @var CacheItemInterface[]
     */
    private $cacheItem = [];

    public function __construct(CacheItemPoolInterface $cache)
    {
        $this->cache = $cache;
    }

    /**
     * @param string $keyString
     * @return string
     */
    public function getCacheKey($keyString)
    {
        return sha1($keyString);
    }

    /**
     * @param STRING $cacheKey
     * @return string|null
     * @throws CacheException
     */
    public function get($cacheKey)
    {
        $cacheItem = $this->cache->getItem($cacheKey);

        return $cacheItem->isHit() ? $cacheItem->get() : null;
    }

    /**
     * @param string $cacheKey
     * @param array $value
     * @throws CacheException
     */
    public function set($cacheKey, $value)
    {
        $cacheItem = $this->cache->getItem($cacheKey);

        if (!$cacheItem->isHit() || $cacheItem->get() !== $value) {
            $cacheItem
                ->set($value)
                ->expiresAt(
                    (new DateTime())->modify('+1 day')
                );
        }
    }

}
```

```
<?php

namespace src\Cache;

class CacheException extends \Exception
{

}
```

```
<?php

namespace src\Integlration;

use Throwable;

class APIException extends \Exception
{
    /**
     * @var int
     */
    private $httpCode;
    
    /**
     * @var string
     */
    private $responseBody;

    public function __construct($message = "", $httpCode = 500, $responseBody = '', $code = 0, Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);

        $this->httpCode = $httpCode;
        $this->responseBody = $responseBody;
    }

    /**
     * @return int
     */
    public function getHttpCode()
    {
        return $this->httpCode;
    }

    /**
     * @return string
     */
    public function getResponseBody()
    {
        return $this->responseBody;
    }
}
```

```
<?php

namespace src\Data;

class InvalidResponseDataException extends \Exception
{

}
```