Completed
Push — master ( eb4f5d...fec2a8 )
by Lars
02:31
created

Cache   C

Complexity

Total Complexity 73

Size/Duplication

Total Lines 487
Duplicated Lines 4.11 %

Coupling/Cohesion

Components 2
Dependencies 10

Test Coverage

Coverage 35.98%

Importance

Changes 21
Bugs 9 Features 2
Metric Value
wmc 73
c 21
b 9
f 2
lcom 2
cbo 10
dl 20
loc 487
ccs 68
cts 189
cp 0.3598
rs 5.5447

17 Methods

Rating   Name   Duplication   Size   Complexity  
A setCacheIsReady() 0 4 1
A getCacheIsReady() 0 4 1
A getItem() 0 13 3
A calculateStoreKey() 0 4 1
A getPrefix() 0 4 1
A setPrefix() 0 4 1
A setItemToDate() 0 12 2
A setItem() 0 20 4
A removeItem() 10 10 2
A existsItem() 10 10 2
C __construct() 0 42 11
A setActive() 0 4 1
C isCacheActiveForTheCurrentUser() 0 28 7
B getClientIp() 0 18 7
C checkForDev() 0 29 8
A getTheDefaultPrefix() 0 4 4
F autoConnectToAvailableCacheSystem() 0 118 17

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Cache often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Cache, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace voku\cache;
4
5
/**
6
 * Cache: global-cache class
7
 *
8
 * can use different cache-adapter:
9
 * - Redis
10
 * - Memcache / Memcached
11
 * - APC / APCu
12
 * - Xcache
13
 * - Array
14
 *
15
 * @package   voku\cache
16
 */
17
class Cache implements iCache
18
{
19
20
  /**
21
   * @var iAdapter
22
   */
23
  private $adapter;
24
25
  /**
26
   * @var iSerializer
27
   */
28
  private $serializer;
29
30
  /**
31
   * @var string
32
   */
33
  private $prefix = '';
34
35
  /**
36
   * @var bool
37
   */
38
  private $isReady = false;
39
40
  /**
41
   * @var bool
42
   */
43
  private $isActive = true;
44
45
  /**
46
   * @var mixed no cache, if admin-session is set
47
   */
48
  private $isAdminSession = false;
49
50
  /**
51
   * __construct
52
   *
53
   * @param null|iAdapter    $adapter
54
   * @param null|iSerializer $serializer
55
   * @param boolean          $checkForUser check for dev-ip or if cms-user is logged-in
56
   * @param boolean          $cacheEnabled false will disable the cache (use it e.g. for global settings)
57
   * @param string|boolean   $isAdminSession set a user-id, if the user is a admin (so we can disable cache for this user)
58
   */
59 27
  public function __construct($adapter = null, $serializer = null, $checkForUser = true, $cacheEnabled = true, $isAdminSession = false)
60
  {
61 27
    $this->isAdminSession = $isAdminSession;
62
63
    // check for active-cache
64 27
    $this->setActive($cacheEnabled);
65 27
    if ($this->isActive === true && $checkForUser === true) {
66
      $this->setActive($this->isCacheActiveForTheCurrentUser());
67
    }
68
69 27
    if ($this->isActive === true) {
70
71 27
      $this->setPrefix($this->getTheDefaultPrefix());
72
73
      if (
74
          $adapter === null
75 27
          ||
76 27
          !is_object($adapter)
77 27
          ||
78
          !$adapter instanceof iAdapter
79 27
      ) {
80
        $adapter = $this->autoConnectToAvailableCacheSystem();
81
      }
82
83
      // Memcache(d) has his own "serializer", but it seems to be working different as the php-implementation.
84 27
      if (!is_object($serializer) && $serializer === null) {
85
        $serializer = new SerializerIgbinary();
86
      }
87 27
    }
88
89
    // check if we will use the cache
90
    if (
91 1
        $serializer instanceof iSerializer
92 27
        &&
93
        $adapter instanceof iAdapter
94 27
    ) {
95 27
      $this->setCacheIsReady(true);
96
97 27
      $this->adapter = $adapter;
98 27
      $this->serializer = $serializer;
99 27
    }
100 27
  }
101
102
  /**
103
   * enable / disable the cache
104
   *
105
   * @param boolean $isActive
106
   */
107 27
  public function setActive($isActive)
108
  {
109 27
    $this->isActive = (boolean)$isActive;
110 27
  }
111
112
  /**
113
   * check if the current use is a admin || dev || server == client
114
   *
115
   * @return bool
116
   */
117
  public function isCacheActiveForTheCurrentUser()
0 ignored issues
show
Coding Style introduced by
isCacheActiveForTheCurrentUser uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
isCacheActiveForTheCurrentUser uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
118
  {
119
    $active = true;
120
121
    // test the cache, with this GET-parameter
122
    $testCache = isset($_GET['testCache']) ? (int)$_GET['testCache'] : 0;
123
124
    if ($testCache != 1) {
125
      if (
126
        // server == client
127
          (
128
              isset($_SERVER['SERVER_ADDR'])
129
              &&
130
              $_SERVER['SERVER_ADDR'] == $this->getClientIp()
131
          )
132
          ||
133
          // admin is logged-in
134
          $this->isAdminSession
135
          ||
136
          // user is a dev
137
          $this->checkForDev() === true
138
      ) {
139
        $active = false;
140
      }
141
    }
142
143
    return $active;
144
  }
145
146
  /**
147
   * returns the IP address of the client
148
   *
149
   * @param   bool $trust_proxy_headers   Whether or not to trust the
150
   *                                      proxy headers HTTP_CLIENT_IP
151
   *                                      and HTTP_X_FORWARDED_FOR. ONLY
152
   *                                      use if your $_SERVER is behind a
153
   *                                      proxy that sets these values
154
   *
155
   * @return  string
156
   */
157
  private function getClientIp($trust_proxy_headers = false)
0 ignored issues
show
Coding Style introduced by
getClientIp uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
158
  {
159
    $remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'NO_REMOTE_ADDR';
160
161
    if ($trust_proxy_headers) {
162
      return $remoteAddr;
163
    }
164
165
    if (isset($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP']) {
166
      $ip = $_SERVER['HTTP_CLIENT_IP'];
167
    } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR']) {
168
      $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
169
    } else {
170
      $ip = $remoteAddr;
171
    }
172
173
    return $ip;
174
  }
175
176
  /**
177
   * check for developer
178
   *
179
   * @return bool
180
   */
181
  private function checkForDev()
0 ignored issues
show
Coding Style introduced by
checkForDev uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
checkForDev uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
182
  {
183
    $return = false;
184
185
    if (function_exists('checkForDev')) {
186
      $return = checkForDev();
187
    } else {
188
189
      // for testing with dev-address
190
      $noDev = isset($_GET['noDev']) ? (int)$_GET['noDev'] : 0;
191
      $remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'NO_REMOTE_ADDR';
192
193
      if (
194
          $noDev != 1
195
          &&
196
          (
197
              $remoteAddr == '127.0.0.1'
198
              ||
199
              $remoteAddr == '::1'
200
              ||
201
              PHP_SAPI == 'cli'
202
          )
203
      ) {
204
        $return = true;
205
      }
206
    }
207
208
    return $return;
209
  }
210
211
  /**
212
   * set the default-prefix via "SERVER_NAME" + "SESSION"-language
213
   */
214 27
  protected function getTheDefaultPrefix()
0 ignored issues
show
Coding Style introduced by
getTheDefaultPrefix uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
getTheDefaultPrefix uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
215
  {
216 27
    return (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '') . '_' . (isset($_SESSION['language']) ? $_SESSION['language'] : '') . '_' . (isset($_SESSION['language_extra']) ? $_SESSION['language_extra'] : '');
217
  }
218
219
  /**
220
   * auto-connect to the available cache-system on the server
221
   *
222
   * @return iAdapter
223
   */
224
  protected function autoConnectToAvailableCacheSystem()
225
  {
226
    static $adapterCache;
227
228
    if (is_object($adapterCache) && $adapterCache instanceof iAdapter) {
229
      return $adapterCache;
230
    } else {
231
232
      $memcached = null;
233
      $isMemcachedAvailable = false;
234
      if (extension_loaded('memcached')) {
235
        $memcached = new \Memcached();
236
        $isMemcachedAvailable = $memcached->addServer('127.0.0.1', '11211');
237
      }
238
239
      if ($isMemcachedAvailable === false) {
240
        $memcached = null;
241
      }
242
243
      $adapterMemcached = new AdapterMemcached($memcached);
0 ignored issues
show
Bug introduced by
It seems like $memcached can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
244
      if ($adapterMemcached->installed() === true) {
245
246
        // fallback to Memcached
247
        $adapter = $adapterMemcached;
248
249
      } else {
250
251
        $memcache = null;
252
        $isMemcacheAvailable = false;
253
        if (class_exists('\Memcache')) {
254
          $memcache = new \Memcache;
255
          /** @noinspection PhpUsageOfSilenceOperatorInspection */
256
          $isMemcacheAvailable = @$memcache->connect('127.0.0.1', 11211);
257
        }
258
259
        if ($isMemcacheAvailable === false) {
260
          $memcache = null;
261
        }
262
263
        $adapterMemcache = new AdapterMemcache($memcache);
0 ignored issues
show
Bug introduced by
It seems like $memcache can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
264
        if ($adapterMemcache->installed() === true) {
265
266
          // fallback to Memcache
267
          $adapter = $adapterMemcache;
268
269
        } else {
270
271
          $redis = null;
272
          $isRedisAvailable = false;
273
          if (extension_loaded('redis')) {
274
            if (class_exists('\Predis\Client')) {
275
              $redis = new \Predis\Client(
276
                  array(
277
                      'scheme'  => 'tcp',
278
                      'host'    => '127.0.0.1',
279
                      'port'    => 6379,
280
                      'timeout' => '2.0',
281
                  )
282
              );
283
              try {
284
                $redis->connect();
285
                $isRedisAvailable = $redis->getConnection()->isConnected();
286
              } catch (\Exception $e) {
287
                // nothing
288
              }
289
            }
290
          }
291
292
          if ($isRedisAvailable === false) {
293
            $redis = null;
294
          }
295
296
          $adapterRedis = new AdapterPredis($redis);
0 ignored issues
show
Bug introduced by
It seems like $redis can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
297
          if ($adapterRedis->installed() === true) {
298
299
            // fallback to Redis
300
            $adapter = $adapterRedis;
301
302
          } else {
303
304
            $adapterXcache = new AdapterXcache();
305
            if ($adapterXcache->installed() === true) {
306
307
              // fallback to Xcache
308
              $adapter = $adapterXcache;
309
310
            } else {
311
312
              $adapterApc = new AdapterApc();
313
              if ($adapterApc->installed() === true) {
314
315
                // fallback to APC || APCu
316
                $adapter = $adapterApc;
317
318
              } else {
319
320
                $adapterFile = new AdapterFile();
321
                if ($adapterFile->installed() === true) {
322
323
                  // fallback to File-Cache
324
                  $adapter = $adapterFile;
325
326
                } else {
327
                  // no cache-adapter available -> use a array
328
                  $adapter = new AdapterArray();
329
                }
330
              }
331
            }
332
          }
333
        }
334
      }
335
336
      // save to static cache
337
      $adapterCache = $adapter;
338
    }
339
340
    return $adapter;
341
  }
342
343
  /**
344
   * set cacheIsReady state
345
   *
346
   * @param boolean $isReady
347
   */
348 27
  private function setCacheIsReady($isReady)
349
  {
350 27
    $this->isReady = (boolean)$isReady;
351 27
  }
352
353
  /**
354
   * get the cacheIsReady state
355
   *
356
   * @return boolean
357
   */
358 3
  public function getCacheIsReady()
359
  {
360 3
    return $this->isReady;
361
  }
362
363
  /**
364
   * get cached-item by key
365
   *
366
   * @param string $key
367
   *
368
   * @return mixed
369
   */
370 12
  public function getItem($key)
371
  {
372 12
    $storeKey = $this->calculateStoreKey($key);
373
374 12
    if ($this->adapter instanceof iAdapter) {
375 12
      $serialized = $this->adapter->get($storeKey);
376 12
      $value = $serialized ? $this->serializer->unserialize($serialized) : null;
377 12
    } else {
378
      return null;
379
    }
380
381 12
    return $value;
382
  }
383
384
  /**
385
   * calculate store-key (prefix + $rawKey)
386
   *
387
   * @param String $rawKey
388
   *
389
   * @return string
390
   */
391 23
  private function calculateStoreKey($rawKey)
392
  {
393 23
    return $this->getPrefix() . $rawKey;
394
  }
395
396
  /**
397
   * @return mixed
398
   */
399 23
  public function getPrefix()
400
  {
401 23
    return $this->prefix;
402
  }
403
404
  /**
405
   * set prefix [WARNING: do not use if you don't know what you do]
406
   *
407
   * @param string $prefix
408
   */
409 27
  public function setPrefix($prefix)
410
  {
411 27
    $this->prefix = (string)$prefix;
412 27
  }
413
414
  /**
415
   * set cache-item by key => value + date
416
   *
417
   * @param string    $key
418
   * @param mixed     $value
419
   * @param \DateTime $date
420
   *
421
   * @return mixed|void
422
   * @throws \Exception
423
   */
424 5
  public function setItemToDate($key, $value, \DateTime $date)
425
  {
426 5
    $ttl = $date->getTimestamp() - time();
427
428 5
    if ($ttl <= 0) {
429 1
      throw new \Exception('Date in the past.');
430
    }
431
432 4
    $storeKey = $this->calculateStoreKey($key);
433
434 4
    return $this->setItem($storeKey, $value, $ttl);
435
  }
436
437
  /**
438
   * set cache-item by key => value + ttl
439
   *
440
   * @param string $key
441
   * @param mixed  $value
442
   * @param int    $ttl
443
   *
444
   * @return bool
445
   */
446 12
  public function setItem($key, $value, $ttl = 0)
447
  {
448 12
    $storeKey = $this->calculateStoreKey($key);
449
450
    if (
451 12
        $this->adapter instanceof iAdapter
452 12
        &&
453 12
        $this->serializer instanceof iSerializer
454 12
    ) {
455 12
      $serialized = $this->serializer->serialize($value);
456
457 12
      if ($ttl) {
458 6
        return $this->adapter->setExpired($storeKey, $serialized, $ttl);
459
      } else {
460 6
        return $this->adapter->set($storeKey, $serialized);
461
      }
462
    } else {
463
      return false;
464
    }
465
  }
466
467
  /**
468
   * remove cached-item
469
   *
470
   * @param string $key
471
   *
472
   * @return bool
473
   */
474 1 View Code Duplication
  public function removeItem($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
475
  {
476 1
    if ($this->adapter instanceof iAdapter) {
477 1
      $storeKey = $this->calculateStoreKey($key);
478
479 1
      return $this->adapter->remove($storeKey);
480
    } else {
481
      return false;
482
    }
483
  }
484
485
  /**
486
   * check if cached-item exists
487
   *
488
   * @param string $key
489
   *
490
   * @return boolean
491
   */
492 4 View Code Duplication
  public function existsItem($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
493
  {
494 4
    if ($this->adapter instanceof iAdapter) {
495 4
      $storeKey = $this->calculateStoreKey($key);
496
497 4
      return $this->adapter->exists($storeKey);
498
    } else {
499
      return false;
500
    }
501
  }
502
503
}
504