Completed
Push — final ( 76bb1f...eccc79 )
by Georges
8s
created

Driver::getStats()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 15
Code Lines 11

Duplication

Lines 15
Ratio 100 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
c 0
b 0
f 0
nc 8
nop 0
dl 15
loc 15
rs 9.2
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
15
namespace phpFastCache\Drivers\Memcache;
16
17
use Memcache as MemcacheSoftware;
18
use phpFastCache\Core\Pool\DriverBaseTrait;
19
use phpFastCache\Core\Pool\ExtendedCacheItemPoolInterface;
20
use phpFastCache\Entities\DriverStatistic;
21
use phpFastCache\Exceptions\phpFastCacheDriverCheckException;
22
use phpFastCache\Exceptions\phpFastCacheDriverException;
23
use phpFastCache\Exceptions\phpFastCacheInvalidArgumentException;
24
use phpFastCache\Util\MemcacheDriverCollisionDetectorTrait;
25
use Psr\Cache\CacheItemInterface;
26
27
/**
28
 * Class Driver
29
 * @package phpFastCache\Drivers
30
 * @property MemcacheSoftware $instance
31
 */
32
class Driver implements ExtendedCacheItemPoolInterface
33
{
34
    use DriverBaseTrait, MemcacheDriverCollisionDetectorTrait;
35
36
    /**
37
     * @var int
38
     */
39
    protected $memcacheFlags = 0;
40
41
    /**
42
     * Driver constructor.
43
     * @param array $config
44
     * @throws phpFastCacheDriverException
45
     */
46
    public function __construct(array $config = [])
47
    {
48
        self::checkCollision('Memcache');
49
        $this->setup($config);
50
51
        if (!$this->driverCheck()) {
52
            throw new phpFastCacheDriverCheckException(sprintf(self::DRIVER_CHECK_FAILURE, $this->getDriverName()));
53
        } else {
54
            $this->driverConnect();
55
56
            if (array_key_exists('compress_data', $config) && $config[ 'compress_data' ] === true) {
57
                $this->memcacheFlags = MEMCACHE_COMPRESSED;
58
            }
59
        }
60
    }
61
62
    /**
63
     * @return bool
64
     */
65
    public function driverCheck()
66
    {
67
        return class_exists('Memcache');
68
    }
69
70
    /**
71
     * @param \Psr\Cache\CacheItemInterface $item
72
     * @return mixed
73
     * @throws phpFastCacheInvalidArgumentException
74
     */
75 View Code Duplication
    protected function driverWrite(CacheItemInterface $item)
76
    {
77
        /**
78
         * Check for Cross-Driver type confusion
79
         */
80
        if ($item instanceof Item) {
81
            $ttl = $item->getTtl();
82
83
            // Memcache will only allow a expiration timer less than 2592000 seconds,
84
            // otherwise, it will assume you're giving it a UNIX timestamp.
85
            if ($ttl >= 2592000) {
86
                $ttl = $item->getExpirationDate()->getTimestamp();
87
            }
88
89
            return $this->instance->set($item->getKey(), $this->driverPreWrap($item), $this->memcacheFlags, $ttl);
90
        } else {
91
            throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected');
92
        }
93
    }
94
95
    /**
96
     * @param \Psr\Cache\CacheItemInterface $item
97
     * @return null|array
98
     */
99 View Code Duplication
    protected function driverRead(CacheItemInterface $item)
100
    {
101
        $val = $this->instance->get($item->getKey());
102
103
        if ($val === false) {
104
            return null;
105
        } else {
106
            return $val;
107
        }
108
    }
109
110
    /**
111
     * @param \Psr\Cache\CacheItemInterface $item
112
     * @return bool
113
     * @throws phpFastCacheInvalidArgumentException
114
     */
115 View Code Duplication
    protected function driverDelete(CacheItemInterface $item)
116
    {
117
        /**
118
         * Check for Cross-Driver type confusion
119
         */
120
        if ($item instanceof Item) {
121
            return $this->instance->delete($item->getKey());
122
        } else {
123
            throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected');
124
        }
125
    }
126
127
    /**
128
     * @return bool
129
     */
130
    protected function driverClear()
131
    {
132
        return $this->instance->flush();
133
    }
134
135
    /**
136
     * @return bool
137
     */
138
    protected function driverConnect()
139
    {
140
        $this->instance = new MemcacheSoftware();
141
        $servers = (!empty($this->config[ 'servers' ]) && is_array($this->config[ 'servers' ]) ? $this->config[ 'servers' ] : []);
142 View Code Duplication
        if (count($servers) < 1) {
143
            $servers = [
144
              [
145
                'host' => !empty($this->config[ 'host' ]) ? $this->config[ 'host' ] : '127.0.0.1',
146
                'path' => !empty($this->config[ 'path' ]) ? $this->config[ 'path' ] : false,
147
                'port' => !empty($this->config[ 'port' ]) ? $this->config[ 'port' ] : 11211,
148
                'sasl_user' => !empty($this->config[ 'sasl_user' ]) ? $this->config[ 'sasl_user' ] : false,
149
                'sasl_password' =>!empty($this->config[ 'sasl_password' ]) ? $this->config[ 'sasl_password' ]: false,
150
              ],
151
            ];
152
        }
153
154
        foreach ($servers as $server) {
155
            try {
156
                /**
157
                 * If path is provided we consider it as an UNIX Socket
158
                 */
159 View Code Duplication
                if(!empty($server[ 'path' ]) && !$this->instance->addServer($server[ 'path' ], 0)){
160
                    $this->fallback = true;
161
                }else if (!empty($server[ 'host' ]) && !$this->instance->addServer($server[ 'host' ], $server[ 'port' ])) {
162
                    $this->fallback = true;
163
                }
164
165
                if (!empty($server[ 'sasl_user' ]) && !empty($server[ 'sasl_password' ])) {
166
                    throw new phpFastCacheDriverException('Unlike Memcached, Memcache does not support SASL authentication');
167
                }
168
            } catch (\Exception $e) {
169
                $this->fallback = true;
170
            }
171
172
            /**
173
             * Since Memcached does not throw
174
             * any error if not connected ...
175
             */
176
            if(!$this->instance->getServerStatus(!empty($server[ 'path' ]) ? $server[ 'path' ] : $server[ 'host' ], !empty($server[ 'port' ]) ? $server[ 'port' ] : 0)){
177
                throw new phpFastCacheDriverException('Memcache seems to not be connected');
178
            }
179
        }
180
181
        return true;
182
    }
183
184
    /********************
185
     *
186
     * PSR-6 Extended Methods
187
     *
188
     *******************/
189
190
    /**
191
     * @return DriverStatistic
192
     */
193 View Code Duplication
    public function getStats()
194
    {
195
        $stats = (array)$this->instance->getstats();
196
        $stats[ 'uptime' ] = (isset($stats[ 'uptime' ]) ? $stats[ 'uptime' ] : 0);
197
        $stats[ 'version' ] = (isset($stats[ 'version' ]) ? $stats[ 'version' ] : 'UnknownVersion');
198
        $stats[ 'bytes' ] = (isset($stats[ 'bytes' ]) ? $stats[ 'version' ] : 0);
199
200
        $date = (new \DateTime())->setTimestamp(time() - $stats[ 'uptime' ]);
201
202
        return (new DriverStatistic())
203
          ->setData(implode(', ', array_keys($this->itemInstances)))
204
          ->setInfo(sprintf("The memcache daemon v%s is up since %s.\n For more information see RawData.", $stats[ 'version' ], $date->format(DATE_RFC2822)))
205
          ->setRawData($stats)
206
          ->setSize($stats[ 'bytes' ]);
207
    }
208
}