Passed
Pull Request — master (#361)
by Alejandro
05:51
created

CacheFactory   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Test Coverage

Coverage 93.1%

Importance

Changes 0
Metric Value
eloc 37
dl 0
loc 82
ccs 27
cts 29
cp 0.931
rs 10
c 0
b 0
f 0
wmc 15

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __invoke() 0 7 1
A getAdapter() 0 10 4
A buildMemcached() 0 10 2
A addMemcachedServer() 0 8 2
A resolveCacheAdapter() 0 15 6
1
<?php
2
declare(strict_types=1);
3
4
namespace Shlinkio\Shlink\Common\Factory;
5
6
use Doctrine\Common\Cache;
7
use Interop\Container\ContainerInterface;
8
use Interop\Container\Exception\ContainerException;
9
use Memcached;
10
use Shlinkio\Shlink\Core\Options\AppOptions;
11
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
12
use Zend\ServiceManager\Exception\ServiceNotFoundException;
13
use Zend\ServiceManager\Factory\FactoryInterface;
14
use function Functional\contains;
15
use function Shlinkio\Shlink\Common\env;
16
use function sys_get_temp_dir;
17
18
class CacheFactory implements FactoryInterface
19
{
20
    private const VALID_CACHE_ADAPTERS = [
21
        Cache\ApcuCache::class,
22
        Cache\ArrayCache::class,
23
        Cache\FilesystemCache::class,
24
        Cache\PhpFileCache::class,
25
        Cache\MemcachedCache::class,
26
    ];
27
    private const DEFAULT_MEMCACHED_PORT = 11211;
28
29
    /**
30
     * Create an object
31
     *
32
     * @param  ContainerInterface $container
33
     * @param  string $requestedName
34
     * @param  null|array $options
35
     * @return object
36
     * @throws ServiceNotFoundException if unable to resolve the service.
37
     * @throws ServiceNotCreatedException if an exception is raised when
38
     *     creating a service.
39
     * @throws ContainerException if any other error occurs
40
     */
41 6
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
42
    {
43 6
        $appOptions = $container->get(AppOptions::class);
44 6
        $adapter = $this->getAdapter($container);
45 6
        $adapter->setNamespace((string) $appOptions);
46
47 6
        return $adapter;
48
    }
49
50 6
    private function getAdapter(ContainerInterface $container): Cache\CacheProvider
51
    {
52
        // Try to get the adapter from config
53 6
        $config = $container->get('config');
54 6
        if (isset($config['cache']['adapter']) && contains(self::VALID_CACHE_ADAPTERS, $config['cache']['adapter'])) {
55 3
            return $this->resolveCacheAdapter($config['cache']);
56
        }
57
58
        // If the adapter has not been set in config, create one based on environment
59 3
        return env('APP_ENV', 'pro') === 'pro' ? new Cache\ApcuCache() : new Cache\ArrayCache();
60
    }
61
62 3
    private function resolveCacheAdapter(array $cacheConfig): Cache\CacheProvider
63
    {
64 3
        switch ($cacheConfig['adapter']) {
65
            case Cache\ArrayCache::class:
66
            case Cache\ApcuCache::class:
67 1
                return new $cacheConfig['adapter']();
68
            case Cache\FilesystemCache::class:
69
            case Cache\PhpFileCache::class:
70 1
                return new $cacheConfig['adapter']($cacheConfig['options']['dir'] ?? sys_get_temp_dir());
71
            case Cache\MemcachedCache::class:
72 1
                $cache = new Cache\MemcachedCache();
73 1
                $cache->setMemcached($this->buildMemcached($cacheConfig));
74 1
                return $cache;
75
            default:
76
                return new Cache\ArrayCache();
77
        }
78
    }
79
80 1
    private function buildMemcached(array $cacheConfig): Memcached
81
    {
82 1
        $memcached = new Memcached();
83 1
        $servers = $cacheConfig['options']['servers'] ?? [];
84
85 1
        foreach ($servers as $server) {
86 1
            $this->addMemcachedServer($memcached, $server);
87
        }
88
89 1
        return $memcached;
90
    }
91
92 1
    private function addMemcachedServer(Memcached $memcached, array $server): void
93
    {
94 1
        if (! isset($server['host'])) {
95
            return;
96
        }
97 1
        $port = (int) ($server['port'] ?? self::DEFAULT_MEMCACHED_PORT);
98
99 1
        $memcached->addServer($server['host'], $port);
100
    }
101
}
102