MemcachedAdapterFactory::__invoke()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace WShafer\PSR11PhpCache\Adapter;
6
7
use Cache\Adapter\Memcached\MemcachedCachePool;
8
use Memcached;
9
use Psr\Container\ContainerInterface;
10
use WShafer\PSR11PhpCache\Exception\InvalidConfigException;
11
use WShafer\PSR11PhpCache\Exception\MissingExtensionException;
12
13
class MemcachedAdapterFactory implements FactoryInterface
14
{
15
    /** @var \Memcached */
16
    protected $cache;
17
18
    /**
19
     * MemcachedAdapterFactory constructor.
20
     *
21
     * @codeCoverageIgnore
22
     */
23
    public function __construct()
24
    {
25
        if (!extension_loaded('memcached')) {
26
            throw new MissingExtensionException(
27
                'Memcached extension not installed.'
28
            );
29
        }
30
    }
31
32
    /**
33
     * @param ContainerInterface $container
34
     * @param array              $options
35
     *
36
     * @return MemcachedCachePool
37
     */
38 6
    public function __invoke(ContainerInterface $container, array $options): MemcachedCachePool
39
    {
40 6
        $this->cache = $this->getMemcachedInstance($container, $options);
41 4
        return new MemcachedCachePool($this->cache);
42
    }
43
44
    /**
45
     * Added for testing
46
     *
47
     * @return \Memcached
48
     */
49 3
    public function getCache(): \Memcached
50
    {
51 3
        return $this->cache;
52
    }
53
54 6
    protected function getMemcachedInstance(ContainerInterface $container, array $options)
55
    {
56
        if (
57 6
            empty($options['service'])
58 6
            && empty($options['servers'])
59
        ) {
60 1
            throw new InvalidConfigException(
61 1
                'You must provide either a container service or at least one server to use'
62
            );
63
        }
64
65 5
        if (!empty($options['service'])) {
66 1
            return $this->getInstanceFromContainer($container, $options['service']);
67
        }
68
69 4
        return $this->getInstanceFromConfig($options);
70
    }
71
72 1
    protected function getInstanceFromContainer(ContainerInterface $container, $name)
73
    {
74 1
        return $container->get($name);
75
    }
76
77 4
    protected function getInstanceFromConfig(array $options): Memcached
78
    {
79 4
        $persistentId = $options['persistentId'] ?? null;
80 4
        $servers = $options['servers'] ?? [];
81 4
        $memcachedOptions = $options['memcachedOptions'] ?? [];
82
83 4
        $instance = new Memcached($persistentId);
84
85 4
        foreach ($servers as $server) {
86 4
            $this->addServer($instance, $server);
87
        }
88
89 3
        foreach ($memcachedOptions as $key => $value) {
90 1
            $instance->setOption($key, $value);
91
        }
92
93 3
        return $instance;
94
    }
95
96 4
    protected function addServer(Memcached $instance, $server): void
97
    {
98 4
        $serverList = $instance->getServerList();
99
100 4
        $host = $server['host'] ?? null;
101 4
        $port = $server['port'] ?? 11211;
102 4
        $weight = $server['weight'] ?? 0;
103
104 4
        if (empty($host)) {
105 1
            throw new InvalidConfigException(
106 1
                "Invalid host provided for Memcached server"
107
            );
108
        }
109
110 3
        foreach ($serverList as $addedServer) {
111
            if (
112 2
                $addedServer['host'] === $host
113 2
                && $addedServer['port'] === $port
114
            ) {
115
                // Server already added skipping
116 2
                return;
117
            }
118
        }
119
120 3
        $instance->addServer($host, $port, $weight);
121 3
    }
122
}
123