Passed
Push — v7 ( ecaaea...ac44be )
by Georges
01:41
created

CacheManager::getInstance()   C

Complexity

Conditions 15
Paths 200

Size

Total Lines 61
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 41
nc 200
nop 3
dl 0
loc 61
rs 5.6638
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 *
4
 * This file is part of phpFastCache.
5
 *
6
 * @license MIT License (MIT)
7
 *
8
 * For full copyright and license information, please see the docs/CREDITS.txt file.
9
 *
10
 * @author Khoa Bui (khoaofgod)  <[email protected]> http://www.phpfastcache.com
11
 * @author Georges.L (Geolim4)  <[email protected]>
12
 *
13
 */
14
declare(strict_types=1);
15
16
namespace Phpfastcache;
17
18
use Phpfastcache\Config\ConfigurationOption;
19
use Phpfastcache\Core\Pool\ExtendedCacheItemPoolInterface;
20
use Phpfastcache\Exceptions\{
21
  PhpfastcacheDeprecatedException, PhpfastcacheDriverCheckException, PhpfastcacheDriverNotFoundException, PhpfastcacheInstanceNotFoundException, PhpfastcacheInvalidArgumentException, PhpfastcacheInvalidConfigurationException, PhpfastcacheLogicException, PhpfastcacheUnsupportedOperationException
22
};
23
use Phpfastcache\Util\ClassNamespaceResolverTrait;
24
25
/**
26
 * Class CacheManager
27
 * @package phpFastCache
28
 *
29
 * @method static ExtendedCacheItemPoolInterface Apc() Apc($config = []) Return a driver "Apc" instance
30
 * @method static ExtendedCacheItemPoolInterface Apcu() Apcu($config = []) Return a driver "Apcu" instance
31
 * @method static ExtendedCacheItemPoolInterface Cassandra() Cassandra($config = []) Return a driver "Cassandra" instance
32
 * @method static ExtendedCacheItemPoolInterface Cookie() Cookie($config = []) Return a driver "Cookie" instance
33
 * @method static ExtendedCacheItemPoolInterface Couchbase() Couchbase($config = []) Return a driver "Couchbase" instance
34
 * @method static ExtendedCacheItemPoolInterface Couchdb() Couchdb($config = []) Return a driver "Couchdb" instance
35
 * @method static ExtendedCacheItemPoolInterface Devnull() Devnull($config = []) Return a driver "Devnull" instance
36
 * @method static ExtendedCacheItemPoolInterface Files() Files($config = []) Return a driver "files" instance
37
 * @method static ExtendedCacheItemPoolInterface Leveldb() Leveldb($config = []) Return a driver "Leveldb" instance
38
 * @method static ExtendedCacheItemPoolInterface Memcache() Memcache($config = []) Return a driver "Memcache" instance
39
 * @method static ExtendedCacheItemPoolInterface Memcached() Memcached($config = []) Return a driver "Memcached" instance
40
 * @method static ExtendedCacheItemPoolInterface Memstatic() Memstatic($config = []) Return a driver "Memstatic" instance
41
 * @method static ExtendedCacheItemPoolInterface Mongodb() Mongodb($config = []) Return a driver "Mongodb" instance
42
 * @method static ExtendedCacheItemPoolInterface Predis() Predis($config = []) Return a driver "Predis" instance
43
 * @method static ExtendedCacheItemPoolInterface Redis() Redis($config = []) Return a driver "Pedis" instance
44
 * @method static ExtendedCacheItemPoolInterface Riak() Riak($config = []) Return a driver "Riak" instance
45
 * @method static ExtendedCacheItemPoolInterface Sqlite() Sqlite($config = []) Return a driver "Sqlite" instance
46
 * @method static ExtendedCacheItemPoolInterface Ssdb() Ssdb($config = []) Return a driver "Ssdb" instance
47
 * @method static ExtendedCacheItemPoolInterface Wincache() Wincache($config = []) Return a driver "Wincache" instance
48
 * @method static ExtendedCacheItemPoolInterface Xcache() Xcache($config = []) Return a driver "Xcache" instance
49
 * @method static ExtendedCacheItemPoolInterface Zenddisk() Zenddisk($config = []) Return a driver "Zend disk cache" instance
50
 * @method static ExtendedCacheItemPoolInterface Zendshm() Zendshm($config = []) Return a driver "Zend memory cache" instance
51
 *
52
 */
53
class CacheManager
54
{
55
    const AUTOMATIC_DRIVER_CLASS = 'Auto';
56
57
    use ClassNamespaceResolverTrait;
58
59
    /**
60
     * @var ConfigurationOption
61
     */
62
    protected static $config;
63
64
    /**
65
     * @var int
66
     */
67
    public static $ReadHits = 0;
68
69
    /**
70
     * @var int
71
     */
72
    public static $WriteHits = 0;
73
74
    /**
75
     * @var string
76
     */
77
    protected static $namespacePath;
78
79
    /**
80
     * @var ExtendedCacheItemPoolInterface[]
81
     */
82
    protected static $instances = [];
83
84
    /**
85
     * @var array
86
     */
87
    protected static $driverOverrides = [];
88
89
    /**
90
     * @var array
91
     */
92
    protected static $driverCustoms = [];
93
94
    /**
95
     * @param string $driver
96
     * @param array|ConfigurationOption $config
97
     * @param string $instanceId
98
     *
99
     * @return ExtendedCacheItemPoolInterface
100
     *
101
     * @throws PhpfastcacheDriverCheckException
102
     * @throws PhpfastcacheInvalidConfigurationException
103
     * @throws PhpfastcacheDriverNotFoundException
104
     * @throws PhpfastcacheInvalidArgumentException
105
     */
106
    public static function getInstance($driver = 'auto', $config = null, $instanceId = null): ExtendedCacheItemPoolInterface
107
    {
108
        static $badPracticeOmeter = [];
109
110
        if ($instanceId !== null && !\is_string($instanceId)) {
0 ignored issues
show
introduced by
The condition is_string($instanceId) is always true.
Loading history...
111
            throw new PhpfastcacheInvalidArgumentException('The Instance ID must be a string');
112
        }
113
114
        if (\is_array($config)) {
115
            $config = new ConfigurationOption($config);
116
            trigger_error(
117
              'The CacheManager will drops the support of primitive configuration arrays, use a "\Phpfastcache\Config\ConfigurationOption" object instead',
118
              E_USER_DEPRECATED
119
            );
120
        }elseif ($config === null){
121
            $config = self::getDefaultConfig();
122
        }else if(!($config instanceof ConfigurationOption)){
0 ignored issues
show
introduced by
$config is always a sub-type of Phpfastcache\Config\ConfigurationOption.
Loading history...
123
            throw new PhpfastcacheInvalidArgumentException(\sprintf('Unsupported config type: %s', gettype($config)));
124
        }
125
126
        $driver = self::standardizeDriverName($driver);
127
128
        if (!$driver || $driver === self::AUTOMATIC_DRIVER_CLASS) {
129
            $driver = self::getAutoClass($config);
130
        }
131
132
        $instance = $instanceId ?: md5($driver . \serialize($config->toArray()));
133
134
        if (!isset(self::$instances[ $instance ])) {
135
            $badPracticeOmeter[ $driver ] = 1;
136
            $driverClass = self::getDriverClass($driver);
137
            try {
138
                if (\class_exists($driverClass)) {
139
                    $configClass = $driverClass::getConfigClass();
140
                    self::$instances[ $instance ] = new $driverClass(new $configClass($config->toArray()), $instance);
141
                    self::$instances[ $instance ]->setEventManager(EventManager::getInstance());
142
                } else {
143
                    throw new PhpfastcacheDriverNotFoundException(\sprintf('The driver "%s" does not exists', $driver));
144
                }
145
            } catch (PhpfastcacheDriverCheckException $e) {
146
                if ($config->getFallback()) {
147
                    try {
148
                        $fallback = $config->getFallback();
149
                        $config->setFallback('');
150
                        trigger_error(\sprintf('The "%s" driver is unavailable at the moment, the fallback driver "%s" has been used instead.', $driver, $fallback), E_USER_WARNING);
151
                        return self::getInstance($fallback, $config->getFallbackConfig());
152
                    } catch (PhpfastcacheInvalidArgumentException $e) {
153
                        throw new PhpfastcacheInvalidConfigurationException('Invalid fallback driver configuration', 0, $e);
154
                    }
155
                } else {
156
                    throw new PhpfastcacheDriverCheckException($e->getMessage(), $e->getCode(), $e);
157
                }
158
            }
159
        } else if ($badPracticeOmeter[ $driver ] >= 2) {
160
            trigger_error('[' . $driver . '] Calling many times CacheManager::getInstance() for already instanced drivers is a bad practice and have a significant impact on performances.
161
           See https://github.com/PHPSocialNetwork/phpfastcache/wiki/[V5]-Why-calling-getInstance%28%29-each-time-is-a-bad-practice-%3F');
162
        }
163
164
        $badPracticeOmeter[ $driver ]++;
165
166
        return self::$instances[ $instance ];
167
    }
168
169
    /**
170
     * @param string $instanceId
171
     *
172
     * @return ExtendedCacheItemPoolInterface
173
     *
174
     * @throws PhpfastcacheInvalidArgumentException
175
     * @throws PhpfastcacheInstanceNotFoundException
176
     */
177
    public static function getInstanceById($instanceId): ExtendedCacheItemPoolInterface
178
    {
179
        if ($instanceId !== null && !\is_string($instanceId)) {
0 ignored issues
show
introduced by
The condition is_string($instanceId) is always true.
Loading history...
180
            throw new PhpfastcacheInvalidArgumentException('The Instance ID must be a string');
181
        }
182
183
        if (isset(self::$instances[ $instanceId ])) {
184
            return self::$instances[ $instanceId ];
185
        }
186
187
        throw new PhpfastcacheInstanceNotFoundException(\sprintf('Instance ID %s not found', $instanceId));
188
    }
189
190
    /**
191
     * This method is intended for internal
192
     * use only and should not be used for
193
     * any external development use the
194
     * getInstances() method instead
195
     *
196
     * @internal
197
     * @return ExtendedCacheItemPoolInterface[]
198
     */
199
    public static function getInstances(): array
200
    {
201
        return self::$instances;
202
    }
203
204
    /**
205
     * This method is intended for internal
206
     * use only and should not be used for
207
     * any external development use the
208
     * getInstances() method instead
209
     *
210
     * @todo Use a proper way to passe them as a reference ?
211
     * @internal
212
     * @return ExtendedCacheItemPoolInterface[]
213
     */
214
    public static function &getInternalInstances(): array
215
    {
216
        return self::$instances;
217
    }
218
219
    /**
220
     * @param ConfigurationOption $config
221
     * @return string
222
     * @throws PhpfastcacheDriverCheckException
223
     * @throws \Phpfastcache\Exceptions\PhpfastcacheLogicException
224
     */
225
    public static function getAutoClass(ConfigurationOption $config): string
226
    {
227
        static $autoDriver;
228
229
        if ($autoDriver === null) {
230
            foreach (self::getDriverList() as $driver) {
231
                try {
232
                    self::getInstance($driver, $config);
233
                    $autoDriver = $driver;
234
                    break;
235
                } catch (PhpfastcacheDriverCheckException $e) {
236
                    continue;
237
                }
238
            }
239
        }
240
241
        if(!$autoDriver || !\is_string($autoDriver)){
242
            throw new PhpfastcacheLogicException('Unable to find out a valid driver automatically');
243
        }
244
245
        return $autoDriver;
246
    }
247
248
    /**
249
     * @param string $name
250
     * @param array $arguments
251
     * @return \Psr\Cache\ExtendedCacheItemPoolInterface
0 ignored issues
show
Bug introduced by
The type Psr\Cache\ExtendedCacheItemPoolInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
252
     */
253
    public static function __callStatic(string $name, array $arguments): ExtendedCacheItemPoolInterface
254
    {
255
        $options = (\array_key_exists(0, $arguments) && \is_array($arguments) ? $arguments[ 0 ] : []);
256
257
        return self::getInstance($name, $options);
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::getInstance($name, $options) returns the type Phpfastcache\Core\Pool\E...dCacheItemPoolInterface which is incompatible with the documented return type Psr\Cache\ExtendedCacheItemPoolInterface.
Loading history...
258
    }
259
260
    /**
261
     * @return bool
262
     */
263
    public static function clearInstances(): bool
264
    {
265
        self::$instances = [];
266
267
        gc_collect_cycles();
268
        return !\count(self::$instances);
269
    }
270
271
    /**
272
     * @return string
273
     */
274
    public static function getNamespacePath(): string
275
    {
276
        return self::$namespacePath ?: self::getDefaultNamespacePath();
277
    }
278
279
    /**
280
     * @return string
281
     */
282
    public static function getDefaultNamespacePath(): string
283
    {
284
        return  __NAMESPACE__ . '\Drivers\\';
285
    }
286
287
    /**
288
     * @param string $path
289
     * @deprecated This method has been deprecated as of V7, please use driver override feature instead
290
     */
291
    public static function setNamespacePath($path)
292
    {
293
        trigger_error('This method has been deprecated as of V7, please use cache manager "override" or "custom driver" features instead', E_USER_DEPRECATED);
294
        self::$namespacePath = \trim($path, "\\") . '\\';
295
    }
296
297
    /**
298
     * @param ConfigurationOption $config
299
     */
300
    public static function setDefaultConfig(ConfigurationOption $config)
301
    {
302
        self::$config = $config;
303
    }
304
305
    /**
306
     * @return ConfigurationOption
307
     */
308
    public static function getDefaultConfig(): ConfigurationOption
309
    {
310
        return self::$config ?: self::$config = new ConfigurationOption();
311
    }
312
313
    /**
314
     * @return array
315
     * @deprecated As of V7 will be removed soon or later, use CacheManager::getDriverList() instead
316
     */
317
    public static function getStaticSystemDrivers(): array
318
    {
319
        trigger_error(\sprintf('Method "%s" is deprecated as of the V7 and will be removed soon or later, use CacheManager::getDriverList() instead.', __METHOD__), E_USER_DEPRECATED);
320
        return [
321
          'Apc',
322
          'Apcu',
323
          'Cassandra',
324
          'Couchbase',
325
          'Couchdb',
326
          'Devnull',
327
          'Files',
328
          'Leveldb',
329
          'Memcache',
330
          'Memcached',
331
          'Memstatic',
332
          'Mongodb',
333
          'Predis',
334
          'Redis',
335
          'Riak',
336
          'Ssdb',
337
          'Sqlite',
338
          'Wincache',
339
          'Xcache',
340
          'Zenddisk',
341
          'Zendshm',
342
        ];
343
    }
344
345
    /**
346
     * @return array
347
     * @deprecated As of V7 will be removed soon or later, use CacheManager::getDriverList() instead
348
     */
349
    public static function getStaticAllDrivers(): array
350
    {
351
        trigger_error(\sprintf('Method "%s" is deprecated as of the V7 and will be removed soon or later, use CacheManager::getDriverList() instead.', __METHOD__), E_USER_DEPRECATED);
352
        return \array_merge(self::getStaticSystemDrivers(), [
1 ignored issue
show
Deprecated Code introduced by
The function Phpfastcache\CacheManage...etStaticSystemDrivers() has been deprecated: As of V7 will be removed soon or later, use CacheManager::getDriverList() instead ( Ignorable by Annotation )

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

352
        return \array_merge(/** @scrutinizer ignore-deprecated */ self::getStaticSystemDrivers(), [

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
353
          'Devtrue',
354
          'Devfalse',
355
          'Cookie',
356
        ]);
357
    }
358
359
    /**
360
     * @return string[]
361
     * @throws PhpfastcacheUnsupportedOperationException
362
     */
363
    public static function getDriverList(): array
364
    {
365
        static $driverList;
366
367
        if(self::getDefaultNamespacePath() === self::getNamespacePath()){
368
            if($driverList === null){
369
                $prefix = 'Phpfastcache\Drivers\\';
370
                $classMap = self::createClassMap(__DIR__ . '/Drivers');
371
                $driverList = [];
372
373
                foreach ($classMap as $class => $file) {
374
                    $driverList[] = str_replace($prefix, '', substr($class, 0, strrpos($class, '\\') ));
375
                }
376
377
                $driverList = array_values(array_unique($driverList));
378
            }
379
380
            $driverList = array_merge($driverList, array_keys(self::$driverCustoms));
381
382
            sort($driverList);
383
384
            return $driverList;
385
        }
386
387
        throw new PhpfastcacheUnsupportedOperationException('Cannot get the driver list if the default namespace path has changed.');
388
    }
389
390
    /**
391
     * @param string $driverName
392
     * @return string
393
     */
394
    public static function standardizeDriverName(string $driverName): string
395
    {
396
        return \ucfirst(\strtolower(\trim($driverName)));
397
    }
398
399
    /**
400
     * @param string $driverName
401
     * @return string
402
     */
403
    public static function getDriverClass(string $driverName): string
404
    {
405
        if(!empty(self::$driverCustoms[$driverName])){
406
            $driverClass = self::$driverCustoms[$driverName];
407
        }else if(!empty(self::$driverOverrides[$driverName])){
408
            $driverClass = self::$driverOverrides[$driverName];
409
        } else{
410
            $driverClass = self::getNamespacePath() . $driverName . '\Driver';
411
        }
412
413
        return $driverClass;
414
    }
415
416
    /**
417
     * @param string $driverName
418
     * @param string $className
419
     * @throws \Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException
420
     * @throws \Phpfastcache\Exceptions\PhpfastcacheLogicException
421
     * @throws \Phpfastcache\Exceptions\PhpfastcacheUnsupportedOperationException
422
     * @return void
423
     */
424
    public static function addCustomDriver(string $driverName, string $className){
425
        $driverName = self::standardizeDriverName($driverName);
426
427
        if(empty($driverName)){
428
            throw new PhpfastcacheInvalidArgumentException("Can't add a custom driver because its name is empty");
429
        }
430
431
        if(!\class_exists($className)){
432
            throw new PhpfastcacheInvalidArgumentException(
433
              sprintf("Can't add '%s' because the class '%s' does not exists", $driverName, $className)
434
            );
435
        }
436
437
        if(!empty(self::$driverCustoms[$driverName])){
438
            throw new PhpfastcacheLogicException(sprintf("Driver '%s' has been already added", $driverName));
439
        }
440
441
        if(\in_array($driverName, self::getDriverList(), true)){
442
            throw new PhpfastcacheLogicException(sprintf("Driver '%s' is already a part of the PhpFastCache core", $driverName));
443
        }
444
445
        self::$driverCustoms[$driverName] = $className;
446
    }
447
448
    /**
449
     * @param string $driverName
450
     * @throws \Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException
451
     * @throws \Phpfastcache\Exceptions\PhpfastcacheLogicException
452
     * @return void
453
     */
454
    public static function removeCustomDriver(string $driverName)
455
    {
456
        $driverName = self::standardizeDriverName($driverName);
457
458
        if(empty($driverName)){
459
            throw new PhpfastcacheInvalidArgumentException("Can't remove a custom driver because its name is empty");
460
        }
461
462
        if(!isset(self::$driverCustoms[$driverName])){
463
            throw new PhpfastcacheLogicException(sprintf("Driver '%s' does not exists", $driverName));
464
        }
465
466
        unset(self::$driverCustoms[$driverName]);
467
    }
468
469
    /**
470
     * @param string $driverName
471
     * @param string $className
472
     * @throws \Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException
473
     * @throws \Phpfastcache\Exceptions\PhpfastcacheLogicException
474
     * @throws \Phpfastcache\Exceptions\PhpfastcacheUnsupportedOperationException
475
     * @return void
476
     */
477
    public static function addCoreDriverOverride(string $driverName, string $className){
478
        $driverName = self::standardizeDriverName($driverName);
479
480
        if(empty($driverName)){
481
            throw new PhpfastcacheInvalidArgumentException("Can't add a core driver override because its name is empty");
482
        }
483
484
        if(!\class_exists($className)){
485
            throw new PhpfastcacheInvalidArgumentException(
486
              sprintf("Can't override '%s' because the class '%s' does not exists", $driverName, $className)
487
            );
488
        }
489
490
        if(!empty(self::$driverOverrides[$driverName])){
491
            throw new PhpfastcacheLogicException(sprintf("Driver '%s' has been already overridden", $driverName));
492
        }
493
494
        if(!\in_array($driverName, self::getDriverList(), true)){
495
            throw new PhpfastcacheLogicException(sprintf("Driver '%s' can't be overridden since its not a part of the PhpFastCache core", $driverName));
496
        }
497
498
        self::$driverOverrides[$driverName] = $className;
499
    }
500
501
    /**
502
     * @param string $driverName
503
     * @throws \Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException
504
     * @throws \Phpfastcache\Exceptions\PhpfastcacheLogicException
505
     * @return void
506
     */
507
    public static function removeCoreDriverOverride(string $driverName)
508
    {
509
        $driverName = self::standardizeDriverName($driverName);
510
511
        if(empty($driverName)){
512
            throw new PhpfastcacheInvalidArgumentException("Can't remove a core driver override because its name is empty");
513
        }
514
515
        if(!isset(self::$driverOverrides[$driverName])){
516
            throw new PhpfastcacheLogicException(sprintf("Driver '%s' were not overridden", $driverName));
517
        }
518
519
        unset(self::$driverOverrides[$driverName]);
520
    }
521
}
522