Passed
Push — 0.8.x ( dc0566...6e510b )
by Alexander
06:23 queued 03:10
created

CacheManager::createArrayDriver()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * Lenevor Framework
5
 *
6
 * LICENSE
7
 *
8
 * This source file is subject to the new BSD license that is bundled
9
 * with this package in the file license.md.
10
 * It is also available through the world-wide-web at this URL:
11
 * https://lenevor.com/license
12
 * If you did not receive a copy of the license and are unable to
13
 * obtain it through the world-wide-web, please send an email
14
 * to [email protected] so we can send you a copy immediately.
15
 *
16
 * @package     Lenevor
17
 * @subpackage  Base
18
 * @link        https://lenevor.com
19
 * @copyright   Copyright (c) 2019 - 2023 Alexander Campo <[email protected]>
20
 * @license     https://opensource.org/licenses/BSD-3-Clause New BSD license or see https://lenevor.com/license or see /license.md
21
 */
22
23
namespace Syscodes\Components\Cache;
24
25
use Closure;
26
use Syscodes\Components\Cache\Store\ApcStore;
27
use Syscodes\Components\Cache\Store\FileStore;
28
use Syscodes\Components\Cache\Store\NullStore;
29
use Syscodes\Components\Contracts\Cache\Store;
30
use Syscodes\Components\Cache\Store\ApcWrapper;
31
use Syscodes\Components\Cache\Store\ArrayStore;
32
use Syscodes\Components\Cache\Store\RedisStore;
33
use Syscodes\Components\Cache\Store\DatabaseStore;
34
use Syscodes\Components\Cache\Store\MemcachedStore;
35
use Syscodes\Components\Cache\Exceptions\CacheException;
36
use Syscodes\Components\Contracts\Cache\Factory as FactoryContract;
37
38
/**
39
 * Class cache manager.
40
 * 
41
 * This class is responsible for loading any available cache driver.
42
 */
43
class CacheManager implements FactoryContract
44
{
45
    /**
46
     * The application instance.
47
     * 
48
     * @var \Syscodes\Components\Contracts\Core\Application $app
49
     */
50
    protected $app;
51
52
    /**
53
     * The registered custom drivers.
54
     * 
55
     * @var array $customDriver
56
     */
57
    protected $customDriver;
58
59
    /**
60
     * The cache store implementation.
61
     * 
62
     * @var array $stores
63
     */
64
    protected $stores = [];
65
66
    /**
67
     * Constructor. Create a new cache manager instance.
68
     * 
69
     * @param  \Syscodes\Components\Contracts\Core\Application  $app
70
     * 
71
     * @return void  
72
     */
73
    public function __construct($app)
74
    {
75
        $this->app = $app;
76
    }
77
78
    /**
79
     * Get a cache driver instance.
80
     * 
81
     * @param  string|null
82
     * 
83
     * @return \Syscodes\Components\Cache\CacheRepository
84
     */
85
    public function driver(string $driver = null)
86
    {
87
        return $this->store($driver);
88
    }
89
    
90
    /**
91
     * Get a cache store instance by name.
92
     * 
93
     * @param  string|null  $name
94
     * 
95
     * @return \Syscodes\Components\Cache\CacheRepository
96
     */
97
    public function store(string $name = null)
98
    {
99
        $name = $name ?: $this->getDefaultDriver();
100
101
        return $this->stores[$name] = $this->resolve($name);
102
    }
103
104
    /**
105
     * Resolve the given store.
106
     * 
107
     * @param  string  $name
108
     * 
109
     * @return \Syscodes\Components\Cache\CacheRepository
110
     * 
111
     * @throws \CacheException
112
     */
113
    protected function resolve(string $name)
114
    {
115
        $config = $this->getConfig($name);
116
117
        if (is_null($config)) {
0 ignored issues
show
introduced by
The condition is_null($config) is always false.
Loading history...
118
            throw new CacheException(__('cache.storeNotDefined', ['name' => $name]));
119
        }
120
121
        if (isset($this->customDriver[$config['driver']])) {
122
            return $this->callCustomDriver($config);
123
        } else {
124
            $driver = 'create'.ucfirst($config['driver']).'Driver';
125
    
126
            if (method_exists($this, $driver)) {
127
                return $this->{$driver}($config);
128
            } else {
129
                throw new CacheException(__('cache.driverNotSupported', ['config' => $config]));
0 ignored issues
show
Bug introduced by
It seems like __('cache.driverNotSuppo...y('config' => $config)) can also be of type array; however, parameter $message of Syscodes\Components\Cach...xception::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

129
                throw new CacheException(/** @scrutinizer ignore-type */ __('cache.driverNotSupported', ['config' => $config]));
Loading history...
130
            }
131
        }
132
    }
133
134
    /**
135
     * Call a custom driver.
136
     * 
137
     * @param  array  $config
138
     * 
139
     * @return mixed
140
     */
141
    protected function callCustomDriver(array $config): mixed
142
    {
143
        return $this->customDriver[$config['default']]($this->app, $config);
144
    }
145
    
146
    /**
147
     * Get the cache connection configuration.
148
     * 
149
     * @param  string  $name
150
     * 
151
     * @return array
152
     */
153
    protected function getConfig(string $name): array
154
    {
155
        if ( ! is_null($name) && $name !== 'null') {
0 ignored issues
show
introduced by
The condition is_null($name) is always false.
Loading history...
156
            return $this->app['config']["cache.stores.{$name}"];
157
        }
158
        
159
        return ['driver' => 'null'];
160
    }
161
162
    /**
163
     * Create an instance of the Apc cache driver.
164
     * 
165
     * @param  array  $config
166
     * 
167
     * @return \Syscodes\Components\Cache\CacheRepository
168
     */
169
    protected function createApcDriver(array $config)
170
    {
171
        $prefix = $this->getPrefix($config);
172
173
        return $this->getRepository(new ApcStore(new ApcWrapper), $prefix);
0 ignored issues
show
Unused Code introduced by
The call to Syscodes\Components\Cach...anager::getRepository() has too many arguments starting with $prefix. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

173
        return $this->/** @scrutinizer ignore-call */ getRepository(new ApcStore(new ApcWrapper), $prefix);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
174
    }
175
176
    /**
177
     * Create an instance of the Array cache driver.
178
     * 
179
     * @return \Syscodes\Components\Cache\CacheRepository
180
     */
181
    protected function createArrayDriver()
182
    {
183
        return $this->getRepository(new ArrayStore);
184
    }
185
186
    /**
187
     * Create an instance of the File cache driver.
188
     * 
189
     * @param  array  $config
190
     * 
191
     * @return \Syscodes\Components\Cache\CacheRepository
192
     */
193
    protected function createDatabaseDriver(array $config)
194
    {
195
        $connection = $this->app['db']->connection($config['connection'] ?? null);
196
        $table      = $config['table'];
197
        $prefix     = $this->getPrefix($config);
198
        
199
        return $this->repository(new DatabaseStore($connection, $table, $prefix));
0 ignored issues
show
Bug introduced by
The method repository() does not exist on Syscodes\Components\Cache\CacheManager. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

199
        return $this->/** @scrutinizer ignore-call */ repository(new DatabaseStore($connection, $table, $prefix));
Loading history...
200
    }
201
202
    /**
203
     * Create an instance of the File cache driver.
204
     * 
205
     * @param  array  $config
206
     * 
207
     * @return \Syscodes\Components\Cache\CacheRepository
208
     */
209
    protected function createFileDriver(array $config)
210
    {
211
        return $this->getRepository(new FileStore($this->app['files'], $config['path']));
212
    }
213
214
    /**
215
     * Create an instance of the Memcached cache driver.
216
     * 
217
     * @param  array  $config
218
     * 
219
     * @return \Syscodes\Components\Cache\CacheRepository
220
     */
221
    protected function createMemcachedDriver(array $config)
222
    {
223
        $prefix = $this->getPrefix($config);
224
225
        $memcached = $this->app['memcached.connector']->connect(
226
            $config['servers'],
227
            $config['persistentID'] ?? null,
228
            $config['options'] ?? [],
229
            array_filter($config['sasl'] ?? [])
230
        );
231
232
        return $this->getRepository(new MemcachedStore($memcached, $prefix));
233
    }
234
235
    /**
236
     * Create an instance of the Null cache driver.
237
     * 
238
     * @return \Syscodes\Components\Cache\CacheRepository
239
     */
240
    protected function createNullDriver()
241
    {
242
        return $this->getRepository(new NullStore);
243
    }
244
245
    /**
246
     * Create an instance of the Redis cache driver.
247
     * 
248
     * @param  array  $config
249
     * 
250
     * @return \Syscodes\Components\Cache\CacheRepository
251
     */
252
    protected function createRedisDriver(array $config)
253
    {
254
        $redis      = $this->app['redis'];
255
        $prefix     = $this->getPrefix($config);
256
        $connection = $config['connection'] ?? 'default';
257
258
        return $this->getRepository(new RedisStore($redis, $prefix, $connection));
259
    }
260
261
    /**
262
     * Get the cache prefix. 
263
     * 
264
     * @param  array  $config
265
     * 
266
     * @return string
267
     */
268
    protected function getPrefix(array $config): string
269
    {
270
        return $config['prefix'] ?? $this->app['config']['cache.prefix'];
271
    }
272
    
273
    /**
274
     * Create a new cache repository with the given implementation.
275
     * 
276
     * @param  \Syscodes\Components\Contracts\Cache\Store  $store
277
     *
278
     * @return \Syscodes\Components\Cache\CacheRepository
279
     */
280
    public function getRepository(Store $store)
281
    {
282
        return new CacheRepository($store);
283
    }
284
285
    /**
286
     * Get the default cache driver name.
287
     * 
288
     * @return string
289
     */
290
    public function getDefaultDriver(): string
291
    {
292
       return $this->app['config']['cache.default'];
293
    }
294
    
295
    /**
296
     * Set the default cache driver name.
297
     * 
298
     * @param  string  $name
299
     * 
300
     * @return void
301
     */
302
    public function setDefaultDriver(string $name): void
303
    {
304
        $this->app['config']['cache.default'] = $name;
305
    }
306
307
    /**
308
     * Register a custom driver creator Closure.
309
     * 
310
     * @param  string  $driver
311
     * @param  \Closure  $callback
312
     * 
313
     * @return static
314
     */
315
    public function extend(string $driver, Closure $callback): static
316
    {
317
        $this->customDriver[$driver] = $callback->bindTo($this, $this);
318
319
        return $this;
320
    }
321
322
    /**
323
     * Magic method.
324
     * 
325
     * Dynamically call the default driver instance.
326
     * 
327
     * @param  string  $method
328
     * @param  array  $params
329
     * 
330
     * @return mixed
331
     */
332
    public function __call(string $method, array $params)
333
    {
334
        return $this->store()->$method(...$params);
335
    }
336
}