Passed
Push — master ( 074e22...c7a4af )
by Oleg
03:48
created

MemcachedDriver::__destruct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 2
eloc 3
nc 2
nop 0
1
<?php /** MicroMemcachedDriver */
2
3
namespace Micro\Cache\Driver;
4
5
use Micro\Base\Exception;
6
use Micro\Base\IContainer;
7
8
/**
9
 * Class MemcachedDriver
10
 *
11
 * @author Oleg Lunegov <[email protected]>
12
 * @link https://github.com/linpax/microphp-framework
13
 * @copyright Copyright &copy; 2013 Oleg Lunegov
14
 * @license /LICENSE
15
 * @package Micro
16
 * @subpackage Cache\Driver
17
 * @version 1.0
18
 * @since 1.0
19
 */
20
class MemcachedDriver extends BaseCacheDriver
21
{
22
    /** @var \Memcache|\Memcached $driver driver memcache(d) */
23
    protected $driver;
24
25
26
    /**
27
     * Constructor
28
     *
29
     * @access public
30
     *
31
     * @param IContainer $container
32
     * @param array $config config array
33
     *
34
     * @result void
35
     * @throws Exception
36
     */
37
    public function __construct(IContainer $container, array $config = [])
38
    {
39
        parent::__construct($container, $config);
40
41
        if (empty($config['type']) || !$this->check()) {
42
            throw new Exception('Memcache(d) not installed or not select type');
43
        }
44
45
        switch (strtolower($config['type'])) {
46
            case 'memcached':
47
                $this->driver = new \Memcached;
48
                break;
49
50
            case 'memcache':
51
                $this->driver = new \Memcache;
52
                break;
53
54
            default:
55
                throw new Exception('Selected type not valid in the driver');
56
        }
57
58
        if (!empty($config['servers'])) {
59
            $this->driver->addServers($config['servers']);
0 ignored issues
show
Bug introduced by
The method addServers does only exist in Memcached, but not in Memcache.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
60
        } elseif ($config['server']) {
61
            $conf = $config['server'];
62
            $server = [
63
                'hostname' => !empty($conf['hostname']) ? $conf['hostname'] : '127.0.0.1',
64
                'port' => !empty($conf['port']) ? $conf['port'] : 11211,
65
                'weight' => !empty($conf['weight']) ? $conf['weight'] : 1
66
            ];
67
68
            if (get_class($this->driver) === 'Memcached') {
69
                $this->driver->addServer($server['hostname'], $server['port'], $server['weight']);
70
            } else {
71
                $this->driver->addServer($server['hostname'], $server['port'], true, $server['weight']);
72
            }
73
        } else {
74
            throw new Exception('Server(s) not configured');
75
        }
76
    }
77
78
    /**
79
     * @inheritdoc
80
     */
81
    public function check()
82
    {
83
        return (!extension_loaded('memcached') && !extension_loaded('memcache')) ?: true;
84
    }
85
86
    /**
87
     * Destructor
88
     *
89
     * @access public
90
     * @result void
91
     */
92
    public function __destruct()
93
    {
94
        if ($this->driver) {
95
            $this->driver->close();
0 ignored issues
show
Bug introduced by
The method close does only exist in Memcache, but not in Memcached.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
96
        }
97
    }
98
99
    /**
100
     * @inheritdoc
101
     */
102
    public function get($name)
103
    {
104
        $data = $this->driver->get($name);
105
106
        return is_array($data) ? $data[0] : $data;
107
    }
108
109
    /**
110
     * @inheritdoc
111
     */
112
    public function set($name, $value, $duration = 0)
113
    {
114
        switch (get_class($this->driver)) {
115
            case 'Memcached':
116
                return $this->driver->set($name, $value, $duration);
117
                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...
118
119
            case 'Memcache':
120
                return $this->driver->set($name, $value, 0, $duration);
121
                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...
122
123
            default:
124
                return false;
125
        }
126
    }
127
128
    /**
129
     * @inheritdoc
130
     */
131
    public function delete($name)
132
    {
133
        return $this->driver->delete($name);
134
    }
135
136
    /**
137
     * @inheritdoc
138
     */
139
    public function clean()
140
    {
141
        return $this->driver->flush();
142
    }
143
144
    /**
145
     * @inheritdoc
146
     */
147
    public function info()
148
    {
149
        return $this->driver->getStats();
150
    }
151
152
    /**
153
     * @inheritdoc
154
     */
155
    public function getMeta($id)
156
    {
157
        $stored = $this->driver->get($id);
158
        if (count($stored) !== 3) {
159
            return false;
160
        }
161
162
        list($data, $time, $ttl) = $stored;
163
164
        return ['expire' => $time + $ttl, 'mtime' => $time, 'data' => $data];
165
    }
166
167
    /**
168
     * @inheritdoc
169
     */
170
    public function increment($name, $offset = 1)
171
    {
172
        return $this->driver->increment($name, $offset);
173
    }
174
175
    /**
176
     * @inheritdoc
177
     */
178
    public function decrement($name, $offset = 1)
179
    {
180
        return $this->driver->decrement($name, $offset);
181
    }
182
}
183