Completed
Push — master ( 67b201...64a3e6 )
by Lars
02:31 queued 11s
created

CacheAdapterAutoManager   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 225
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 1
dl 0
loc 225
ccs 0
cts 84
cp 0
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A addAdapter() 0 13 1
A getAdapters() 0 6 2
A merge() 0 20 3
A validateAdapter() 0 8 2
A validateCallable() 0 10 3
C getDefaultsForAutoInit() 0 119 9
1
<?php
2
3
declare(strict_types=1);
4
5
namespace voku\cache;
6
7
use voku\cache\Exception\InvalidArgumentException;
8
9
class CacheAdapterAutoManager
10
{
11
    /**
12
     * @var string[]
13
     */
14
    private $adapter = [];
15
16
    /**
17
     * @var callable[]|null[]
18
     */
19
    private $callableFunctions = [];
20
21
    /**
22
     * @param string        $adapter
23
     * @param null|callable $callableFunction
24
     *
25
     * @return $this
26
     *
27
     * @throws InvalidArgumentException
28
     */
29
    public function addAdapter(
30
        string $adapter,
31
        callable $callableFunction = null
32
    ): self
33
    {
34
        $this->validateAdapter($adapter);
35
        $this->validateCallable($callableFunction);
36
37
        $this->adapter[] = $adapter;
38
        $this->callableFunctions[] = $callableFunction;
39
40
        return $this;
41
    }
42
43
    /**
44
     * @return \Generator|\Generator<string, callable>
0 ignored issues
show
Documentation introduced by
The doc-type \Generator|\Generator<string, could not be parsed: Expected "|" or "end of type", but got "<" at position 21. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
45
     */
46
    public function getAdapters(): \Generator
47
    {
48
        foreach ($this->adapter as $key => $value) {
49
            yield $this->adapter[$key] => $this->callableFunctions[$key];
50
        }
51
    }
52
53
    /**
54
     * @param CacheAdapterAutoManager $adapterManager
55
     *
56
     * @return CacheAdapterAutoManager
57
     *
58
     * @throws InvalidArgumentException
59
     */
60
    public function merge(CacheAdapterAutoManager $adapterManager): self
61
    {
62
        foreach ($adapterManager->getAdapters() as $adapterTmp => $callableFunctionTmp) {
63
64
            $this->validateAdapter($adapterTmp);
65
            $this->validateCallable($callableFunctionTmp);
66
67
            $key = array_search($adapterTmp, $this->adapter, true);
68
69
            if ($key) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $key of type false|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
70
                $this->adapter[$key] = $adapterTmp;
71
                $this->callableFunctions[$key] = $callableFunctionTmp;
72
            } else {
73
                $this->adapter[] = $adapterTmp;
74
                $this->callableFunctions[] = $callableFunctionTmp;
75
            }
76
        }
77
78
        return $this;
79
    }
80
81
    /**
82
     * @param string $replaceAdapter
83
     *
84
     * @throws InvalidArgumentException
85
     */
86
    private function validateAdapter(string $replaceAdapter)
87
    {
88
        /** @noinspection PhpUnhandledExceptionInspection */
89
        $interfaces = (new \ReflectionClass($replaceAdapter))->getInterfaces();
90
        if (!array_key_exists(iAdapter::class, $interfaces)) {
91
            throw new InvalidArgumentException('"' . $replaceAdapter . '" did not implement the "iAdapter"-interface [' . print_r($interfaces, true) . ']');
92
        }
93
    }
94
95
    /**
96
     * @param callable $callableFunction
97
     *
98
     * @throws InvalidArgumentException
99
     */
100
    private function validateCallable(callable $callableFunction = null)
101
    {
102
        if (
103
            $callableFunction !== null
104
            &&
105
            !is_callable($callableFunction)
106
        ) {
107
            throw new InvalidArgumentException('$callableFunction is not callable');
108
        }
109
    }
110
111
    /**
112
     * @return CacheAdapterAutoManager
113
     */
114
    public static function getDefaultsForAutoInit(): self
115
    {
116
        $cacheAdapterManager = new self();
117
118
        /** @noinspection PhpUnhandledExceptionInspection */
119
        $cacheAdapterManager->addAdapter(
120
            AdapterMemcached::class,
121
            function () {
122
                $memcached = null;
123
                $isMemcachedAvailable = false;
124
                if (\extension_loaded('memcached')) {
125
                    /** @noinspection PhpComposerExtensionStubsInspection */
126
                    $memcached = new \Memcached();
127
                    /** @noinspection PhpUsageOfSilenceOperatorInspection */
128
                    $isMemcachedAvailable = @$memcached->addServer('127.0.0.1', 11211);
129
                }
130
131
                if (!$isMemcachedAvailable) {
132
                    $memcached = null;
133
                }
134
135
                return $memcached;
136
            }
137
        );
138
139
        /** @noinspection PhpUnhandledExceptionInspection */
140
        $cacheAdapterManager->addAdapter(
141
            AdapterMemcache::class,
142
            function () {
143
                $memcache = null;
144
                $isMemcacheAvailable = false;
145
                /** @noinspection ClassConstantCanBeUsedInspection */
146
                if (\class_exists('\Memcache')) {
147
                    /** @noinspection PhpComposerExtensionStubsInspection */
148
                    $memcache = new \Memcache();
149
                    /** @noinspection PhpUsageOfSilenceOperatorInspection */
150
                    $isMemcacheAvailable = @$memcache->connect('127.0.0.1', 11211);
151
                }
152
153
                if (!$isMemcacheAvailable) {
154
                    $memcache = null;
155
                }
156
157
                return $memcache;
158
            }
159
        );
160
161
        /** @noinspection PhpUnhandledExceptionInspection */
162
        $cacheAdapterManager->addAdapter(
163
            AdapterPredis::class,
164
            function () {
165
                $redis = null;
166
                $isRedisAvailable = false;
167
                if (
168
                    \extension_loaded('redis')
169
                    &&
170
                    \class_exists('\Predis\Client')
171
                ) {
172
                    /** @noinspection PhpUndefinedNamespaceInspection */
173
                    /** @noinspection PhpUndefinedClassInspection */
174
                    $redis = new \Predis\Client(
175
                        [
176
                            'scheme'  => 'tcp',
177
                            'host'    => '127.0.0.1',
178
                            'port'    => 6379,
179
                            'timeout' => '2.0',
180
                        ]
181
                    );
182
183
                    try {
184
                        /** @noinspection PhpUndefinedMethodInspection */
185
                        $redis->connect();
186
                        /** @noinspection PhpUndefinedMethodInspection */
187
                        $isRedisAvailable = $redis->getConnection()->isConnected();
188
                    } catch (\Exception $e) {
189
                        // nothing
190
                    }
191
                }
192
193
                if ($isRedisAvailable === false) {
194
                    $redis = null;
195
                }
196
197
                return $redis;
198
            }
199
        );
200
201
        /** @noinspection PhpUnhandledExceptionInspection */
202
        $cacheAdapterManager->addAdapter(
203
            AdapterXcache::class
204
        );
205
206
        /** @noinspection PhpUnhandledExceptionInspection */
207
        $cacheAdapterManager->addAdapter(
208
            AdapterApcu::class
209
        );
210
211
        /** @noinspection PhpUnhandledExceptionInspection */
212
        $cacheAdapterManager->addAdapter(
213
            AdapterApc::class
214
        );
215
216
        /** @noinspection PhpUnhandledExceptionInspection */
217
        $cacheAdapterManager->addAdapter(
218
            AdapterOpCache::class,
219
            function () {
220
                $cacheDir = \realpath(\sys_get_temp_dir()) . '/simple_php_cache';
221
222
                return $cacheDir;
223
            }
224
        );
225
226
        /** @noinspection PhpUnhandledExceptionInspection */
227
        $cacheAdapterManager->addAdapter(
228
            AdapterArray::class
229
        );
230
231
        return $cacheAdapterManager;
232
    }
233
}
234