---
# System prepended metadata

title: Исходные файлы

---

# Исходные файлы

### src/DataProviderInterface.php
```php
<?php
namespace main;

/**
 * Интерфейс получения данных
 */
interface DataProviderInterface
{
    /**
     * Получить результат
     *
     * @param array $input
     * @return array
     */
    function get(array $input): array;
}

```


### src/CacheDecorator.php
```php
<?php
namespace main;
use Psr\Cache\CacheItemPoolInterface;

/**
 * Кеширующий декоратор
 */
class CacheDecorator implements DataProviderInterface
{
    /**
     * @var CacheItemPoolInterface
     */
    private $cache;

    /**
     * Время кеширования в секундах
     *
     * @var int
     */
    private $cacheTime = 3600 * 24;

    /**
     * @var DataProviderInterface
     */
    private $dataProvider;

    /**
     * @param DataProviderInterface $dataProvider
     * @param CacheItemPoolInterface $cache
     */
    public function __construct(DataProviderInterface $dataProvider, CacheItemPoolInterface $cache)
    {
        $this->dataProvider = $dataProvider;
        $this->cache = $cache;
    }

    /**
     * Время кеширования в секундах
     *
     * @return int
     */
    public function getCacheTime(): int
    {
        return $this->cacheTime;
    }

    /**
     * Установить время кеширования в секундах
     *
     * @param int $cacheTime
     */
    public function setCacheTime(int $cacheTime): void
    {
        $this->cacheTime = $cacheTime;
    }

    /**
     * Получить результат
     *
     * @param array $input
     * @return array
     * @throws \Psr\Cache\InvalidArgumentException
     */
    public function get(array $input): array
    {
        $cacheKey = $this->getCacheKey($input);
        $cacheItem = $this->cache->getItem($cacheKey);

        if ($cacheItem->isHit()) {
            return $cacheItem->get();
        }
        $result = $this->dataProvider->get($input);

        $cacheItem
            ->set($result)
            ->expiresAt(
                (new \DateTime())->add(new \DateInterval("PT{$this->cacheTime}S"))
            );

        $this->cache->save($cacheItem);
        return $result;
    }

    /**
     * Получить ключ кеширования по входящему запросу
     *
     * @param array $input
     * @return string
     */
    private function getCacheKey(array $input): string
    {
        return md5(serialize($input));
    }
}
```

### src/LoggerDecorator.php
```php
<?php
namespace main;
use Psr\Log\LoggerInterface;

/**
 * Логгирующий декоратор
 */
class LoggerDecorator implements DataProviderInterface
{
    /**
     * @var DataProviderInterface
     */
    private $dataProvider;

    /**
     * @var LoggerInterface
     */
    private $logger;

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

    /**
     * Получить результат
     *
     * @param array $input
     * @return array
     */
    public function get(array $input): array
    {
        try {
            return $this->dataProvider->get($input);
        } catch (\Exception $ex) {
            $this->logger->error($ex->getMessage());
            return [];
        }
    }
}
```

# Тесты
### tests/CacheDecoratorTest.php
```php
<?php
namespace tests;
use main\CacheDecorator;
use PHPUnit\Framework\TestCase;

class CacheDecoratorTest extends TestCase
{
    public function testCacheMissResult() {
        $args = ['some'];
        $result = ['result'];

        $mockProvider = $this->createMock('main\DataProviderInterface');
        $mockProvider->method('get')->with($args)->willReturn($result);

        $mockCacheItem = $this->createMock('\Psr\Cache\CacheItemInterface');
        $mockCacheItem->method('isHit')->willReturn(false);

        $mockCacheItem->method('expiresAt')->willReturnCallback(function ($arg) {
            $this->assertEquals((new \DateTime())->modify('+1 minute'), $arg, '', 1e-4);
        });
        $mockCacheItem->method('set')->with($result)->willReturnSelf();

        $mockCache = $this->createMock('\Psr\Cache\CacheItemPoolInterface');
        $mockCache->method('getItem')->willReturn($mockCacheItem);
        $mockCache->expects($this->once())->method('save')->with($mockCacheItem);

        $testProvider = new CacheDecorator($mockProvider, $mockCache);
        $testProvider->setCacheTime(60);
        $this->assertEquals($result, $testProvider->get($args));
    }

    public function testCacheHitResult() {
        $args = ['some'];
        $result = ['result'];

        $mockProvider = $this->createMock('main\DataProviderInterface');
        $mockProvider->expects($this->never())->method('get');

        $mockCacheItem = $this->createMock('\Psr\Cache\CacheItemInterface');
        $mockCacheItem->method('isHit')->willReturn(true);
        $mockCacheItem->method('get')->willReturn($result);

        $mockCache = $this->createMock('\Psr\Cache\CacheItemPoolInterface');
        $mockCache->method('getItem')->willReturn($mockCacheItem);

        $testProvider = new CacheDecorator($mockProvider, $mockCache);
        $this->assertEquals($result, $testProvider->get($args));
    }
}


```

### tests/LoggerDecoratorTest.php
```php
<?
namespace tests;

use main\LoggerDecorator;
use PHPUnit\Framework\TestCase;

class LoggerDecoratorTest extends TestCase
{
    public function testDataProviderException()
    {
        $mockLogger = $this->createMock('Psr\Log\LoggerInterface');
        $mockLogger->expects($this->once())->method('error');

        $mockProvider = $this->createMock('main\DataProviderInterface');
        $mockProvider->method('get')->willThrowException(new \Exception());

        $testDecorator = new LoggerDecorator($mockProvider, $mockLogger);
        $this->assertEquals([], $testDecorator->get(['any-args']));
    }
}

```