Completed
Push — trunk ( 91a948...0e7a2e )
by SuperNova.WS
05:44
created

classCache::getInstance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 7
ccs 0
cts 6
cp 0
crap 6
rs 9.4285
1
<?php
2
/**
3
 *
4
 * @package supernova
5
 * @version #43a15.16#
6
 * @copyright (c) 2009-2017 Gorlum for http://supernova.ws
7
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
8
 *
9
 */
10
11
/**
12
 *
13
 * Basic cacher class that handles different cache engines
14
 * It's pretty smart to handle one cache instance for all application instances (if there is PHP-cacher installed)
15
 * Currently supported only XCache and no-cache (array)
16
 * With no-cache some advanced features would be unaccessible
17
 * Cacher works not only with single values. It's also support multidimensional arrays
18
 * Currently support is a bit limited - for example there is no "walk" function. However basic array abilities supported
19
 * You should NEVER operate with arrays inside of cacher and should ALWAYS use wrap-up functions
20
 *
21
 * @property bool  _INITIALIZED
22
 * @property array lng_stat_usage - Array for locale strings usage statistics
23
 * @property array tables
24
 *
25
 * @package supernova
26
 */
27
class classCache implements ArrayAccess {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
28
  const CACHER_NOT_INIT = -1;
29
  const CACHER_NO_CACHE = 0;
30
  const CACHER_XCACHE = 1;
31
32
  // CACHER_NOT_INIT - not initialized
33
  // CACHER_NO_CACHE - no cache - array() used
34
  // CACHER_XCACHE   - xCache
35
  protected static $mode = self::CACHER_NOT_INIT;
36
  protected static $data;
37
  protected $prefix;
38
39
  protected static $cacheObject;
40
41
  public function __construct($prefIn = 'CACHE_', $init_mode = false) {
42
    if (!($init_mode === false || $init_mode === self::CACHER_NO_CACHE || ($init_mode === self::CACHER_XCACHE && extension_loaded('xcache')))) {
43
      throw new UnexpectedValueException('Wrong work mode or current mode does not supported on your server');
44
    }
45
46
    $this->prefix = $prefIn;
47
    if (extension_loaded('xcache') && ($init_mode === self::CACHER_XCACHE || $init_mode === false)) {
48
      if (self::$mode === self::CACHER_NOT_INIT) {
49
        self::$mode = self::CACHER_XCACHE;
50
      }
51
    } else {
52
      if (self::$mode === self::CACHER_NOT_INIT) {
53
        self::$mode = self::CACHER_NO_CACHE;
54
        if (!self::$data) {
55
          self::$data = array();
56
        }
57
      }
58
    }
59
  }
60
61
  public static function getInstance($prefIn = 'CACHE_', $table_name = '') {
0 ignored issues
show
Unused Code introduced by
The parameter $table_name is not used and could be removed. ( Ignorable by Annotation )

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

61
  public static function getInstance($prefIn = 'CACHE_', /** @scrutinizer ignore-unused */ $table_name = '') {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
62
    if (!isset(self::$cacheObject)) {
63
      $className = get_class();
64
      self::$cacheObject = new $className($prefIn);
65
    }
66
67
    return self::$cacheObject;
68
  }
69
70
  public final function __clone() {
0 ignored issues
show
Coding Style introduced by
As per PSR2, final should precede the visibility keyword.
Loading history...
71
    // You NEVER need to copy cacher object or siblings
72
    throw new BadMethodCallException('Clone is not allowed');
73
  }
74
75
  /**
76
   * @return int
77
   */
78
  public function getMode() {
79
    return self::$mode;
80
  }
81
82
  /**
83
   * @return string
84
   */
85
  public function getPrefix() {
86
    return $this->prefix;
87
  }
88
89
  /**
90
   * @param $prefix
91
   */
92
  public function setPrefix($prefix) {
93
    $this->prefix = $prefix;
94
  }
95
96
  // -------------------------------------------------------------------------
97
  // Here comes low-level functions - those that directly works with cacher engines
98
  // -------------------------------------------------------------------------
99
  public function __set($name, $value) {
100
    switch (self::$mode) {
101
      case self::CACHER_NO_CACHE:
102
        self::$data[$this->prefix . $name] = $value;
103
      break;
104
105
      case self::CACHER_XCACHE:
106
        xcache_set($this->prefix . $name, $value);
107
      break;
108
    }
109
  }
110
111
  public function __get($name) {
112
    switch (self::$mode) {
113
      case self::CACHER_NO_CACHE:
114
        return array_key_exists($this->prefix . $name, self::$data) ? self::$data[$this->prefix . $name] : null;
115
      break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
116
117
      case self::CACHER_XCACHE:
118
        return xcache_get($this->prefix . $name);
119
      break;
120
    }
121
122
    return null;
123
  }
124
125
  public function __isset($name) {
126
    switch (self::$mode) {
127
      case self::CACHER_NO_CACHE:
128
        return isset(self::$data[$this->prefix . $name]);
129
      break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
130
131
      case self::CACHER_XCACHE:
132
        return xcache_isset($this->prefix . $name) && ($this->__get($name) !== null);
133
      break;
134
    }
135
136
    return false;
137
  }
138
139
  public function __unset($name) {
140
    switch (self::$mode) {
141
      case self::CACHER_NO_CACHE:
142
        unset(self::$data[$this->prefix . $name]);
143
      break;
144
145
      case self::CACHER_XCACHE:
146
        xcache_unset($this->prefix . $name);
147
      break;
148
    }
149
  }
150
151
  public function unset_by_prefix($prefix_unset = '') {
152
    static $array_clear;
153
    !$array_clear ? $array_clear = function (&$v, $k, $p) {
154
      strpos($k, $p) === 0 ? $v = null : false;
155
    } : false;
156
157
    switch (self::$mode) {
158
      case self::CACHER_NO_CACHE:
159
//        array_walk(self::$data, create_function('&$v,$k,$p', 'if(strpos($k, $p) === 0)$v = NULL;'), $this->prefix.$prefix_unset);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
160
        array_walk(self::$data, $array_clear, $this->prefix . $prefix_unset);
161
162
        return true;
163
      break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
164
165
      case self::CACHER_XCACHE:
166
        if (!function_exists('xcache_unset_by_prefix')) {
167
          return false;
168
        }
169
170
        return xcache_unset_by_prefix($this->prefix . $prefix_unset);
171
      break;
172
    }
173
174
    return true;
175
  }
176
  // -------------------------------------------------------------------------
177
  // End of low-level functions
178
  // -------------------------------------------------------------------------
179
180
  protected function make_element_name($args, $diff = 0) {
181
    $num_args = count($args);
182
183
    if ($num_args < 1) {
184
      return false;
185
    }
186
187
    $name = '';
188
    $aName = array();
189
    for ($i = 0; $i <= $num_args - 1 - $diff; $i++) {
190
      $name .= "[{$args[$i]}]";
191
      array_unshift($aName, $name);
192
    }
193
194
    return $aName;
195
  }
196
197
  public function array_set() {
198
    $args = func_get_args();
199
    $name = $this->make_element_name($args, 1);
200
201
    if (!$name) {
0 ignored issues
show
introduced by
The condition $name is always false.
Loading history...
202
      return null;
203
    }
204
205
    if ($this->$name[0] === null) {
206
      for ($i = count($name) - 1; $i > 0; $i--) {
207
        $cName = "{$name[$i]}_COUNT";
208
        $cName1 = "{$name[$i-1]}_COUNT";
209
        if ($this->$cName1 == null || $i == 1) {
210
          $this->$cName++;
211
        }
212
      }
213
    }
214
215
    $this->$name[0] = $args[count($args) - 1];
216
217
    return true;
218
  }
219
220
  public function array_get() {
221
    $name = $this->make_element_name(func_get_args());
222
    if (!$name) {
0 ignored issues
show
introduced by
The condition $name is always false.
Loading history...
223
      return null;
224
    }
225
226
    return $this->$name[0];
227
  }
228
229
  public function array_count() {
230
    $name = $this->make_element_name(func_get_args());
231
    if (!$name) {
0 ignored issues
show
introduced by
The condition $name is always false.
Loading history...
232
      return 0;
233
    }
234
    $cName = "{$name[0]}_COUNT";
235
    $retVal = $this->$cName;
236
    if (!$retVal) {
237
      $retVal = null;
238
    }
239
240
    return $retVal;
241
  }
242
243
  public function array_unset() {
244
    $name = $this->make_element_name(func_get_args());
245
246
    if (!$name) {
0 ignored issues
show
introduced by
The condition $name is always false.
Loading history...
247
      return false;
248
    }
249
    $this->unset_by_prefix($name[0]);
250
251
    $count = count($name);
252
    for ($i = 1; $i < $count; $i++) {
253
      $cName = "{$name[$i]}_COUNT";
254
      $cName1 = "{$name[$i-1]}_COUNT";
255
256
      if ($i == 1 || $this->$cName1 === null) {
257
        $this->$cName--;
258
        if ($this->$cName <= 0) {
259
          unset($this->$cName);
260
        }
261
      }
262
    }
263
264
    return true;
265
  }
266
267
  public function dumpData() {
268
    switch (self::$mode) {
269
      case self::CACHER_NO_CACHE:
270
        return dump(self::$data, $this->prefix);
271
      break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
272
273
      default:
274
        return false;
275
      break;
276
    }
277
  }
278
279
  public function reset() {
280
    $this->unset_by_prefix();
281
282
    $this->_INITIALIZED = false;
283
  }
284
285
  public function init($reInit = false) {
0 ignored issues
show
Unused Code introduced by
The parameter $reInit is not used and could be removed. ( Ignorable by Annotation )

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

285
  public function init(/** @scrutinizer ignore-unused */ $reInit = false) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
286
    $this->_INITIALIZED = true;
287
  }
288
289
  public function isInitialized() {
290
    return $this->_INITIALIZED;
291
  }
292
293
  /**
294
   * Whether a offset exists
295
   * @link http://php.net/manual/en/arrayaccess.offsetexists.php
296
   *
297
   * @param mixed $offset <p>
298
   * An offset to check for.
299
   * </p>
300
   *
301
   * @return boolean true on success or false on failure.
302
   * </p>
303
   * <p>
304
   * The return value will be casted to boolean if non-boolean was returned.
305
   * @since 5.0.0
306
   */
307
  public function offsetExists($offset) {
308
    return $this->__isset($offset);
309
  }
310
311
  /**
312
   * Offset to retrieve
313
   * @link http://php.net/manual/en/arrayaccess.offsetget.php
314
   *
315
   * @param mixed $offset <p>
316
   * The offset to retrieve.
317
   * </p>
318
   *
319
   * @return mixed Can return all value types.
320
   * @since 5.0.0
321
   */
322
  public function offsetGet($offset) {
323
    return $this->__get($offset);
324
  }
325
326
  /**
327
   * Offset to set
328
   * @link http://php.net/manual/en/arrayaccess.offsetset.php
329
   *
330
   * @param mixed $offset <p>
331
   * The offset to assign the value to.
332
   * </p>
333
   * @param mixed $value <p>
334
   * The value to set.
335
   * </p>
336
   *
337
   * @return void
338
   * @since 5.0.0
339
   */
340
  public function offsetSet($offset, $value) {
341
    $this->__set($offset, $value);
342
  }
343
344
  /**
345
   * Offset to unset
346
   * @link http://php.net/manual/en/arrayaccess.offsetunset.php
347
   *
348
   * @param mixed $offset <p>
349
   * The offset to unset.
350
   * </p>
351
   *
352
   * @return void
353
   * @since 5.0.0
354
   */
355
  public function offsetUnset($offset) {
356
    $this->__unset($offset);
357
  }
358
359
}
360