Passed
Pull Request — master (#30)
by Alexander
01:23
created

Memcached::iterableToArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 2
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Yiisoft\Cache;
4
5
use DateInterval;
6
use DateTime;
7
use Exception;
8
use Psr\SimpleCache\CacheInterface;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Yiisoft\Cache\CacheInterface. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
9
10
/**
11
 * Memcached implements a cache application component based on [memcached](http://pecl.php.net/package/memcached) PECL
12
 * extension.
13
 *
14
 * Memcached can be configured with a list of memcached servers by settings its {@see Memcached::$servers} property.
15
 * By default, Memcached assumes there is a memcached server running on localhost at port 11211.
16
 *
17
 * See {@see \Psr\SimpleCache\CacheInterface} for common cache operations that MemCached supports.
18
 *
19
 * Note, there is no security measure to protected data in memcached.
20
 * All data in memcached can be accessed by any process running in the system.
21
 */
22
final class Memcached implements CacheInterface
23
{
24
    public const EXPIRATION_INFINITY = 0;
25
26
    /**
27
     * @var \Memcached the Memcached instance
28
     */
29
    private $cache;
30
31
    public function __construct()
32
    {
33
        $this->initCache();
34
    }
35
36
    public function get($key, $default = null)
37
    {
38
        $value = $this->cache->get($key);
39
40
        if ($this->cache->getResultCode() === \Memcached::RES_SUCCESS) {
41
            return $value;
42
        }
43
44
        return $default;
45
    }
46
47
    public function set($key, $value, $ttl = null): bool
48
    {
49
        $expiration = $this->ttlToExpiration($ttl);
50
        if ($expiration < 0) {
51
            return $this->delete($key);
52
        }
53
        return $this->cache->set($key, $value, $expiration);
54
    }
55
56
    public function delete($key): bool
57
    {
58
        return $this->cache->delete($key);
59
    }
60
61
    public function clear(): bool
62
    {
63
        return $this->cache->flush();
64
    }
65
66 17
    public function getMultiple($keys, $default = null)
67
    {
68 17
        $values = $this->cache->getMulti($this->iterableToArray($keys));
69
        return array_merge(array_fill_keys($this->iterableToArray($keys), $default), $values);
70 17
    }
71 17
72
    public function setMultiple($values, $ttl = null): bool
73
    {
74 17
        $expiration = $this->ttlToExpiration($ttl);
75
        return $this->cache->setMulti($this->iterableToArray($values), $expiration);
76 17
    }
77
78
    public function deleteMultiple($keys): bool
79
    {
80
        foreach ($this->cache->deleteMulti($this->iterableToArray($keys)) as $result) {
81
            if ($result === false) {
82
                return false;
83
            }
84
        }
85 17
        return true;
86
    }
87 17
88 17
    public function has($key): bool
89
    {
90
        $this->cache->get($key);
91
        return $this->cache->getResultCode() === \Memcached::RES_SUCCESS;
92
    }
93 17
94 17
    /**
95 17
     * Inits Memcached instance
96 17
     */
97
    private function initCache(): void
98
    {
99
        $this->cache = new \Memcached();
100
    }
101
102
    /**
103
     * Adds a server to the Memcached server pool
104
     * @param MemcachedServer $server
105
     */
106 17
    public function addServer(MemcachedServer $server): void
107
    {
108 17
        $this->cache->addServer($server->getHost(), $server->getPort(), $server->getWeight());
109 17
    }
110
111
    /**
112
     * Converts TTL to expiration
113 17
     * @param $ttl
114 17
     * @return int
115
     */
116
    protected function ttlToExpiration($ttl): int
117
    {
118 17
        $ttl = $this->normalizeTtl($ttl);
119
120
        if ($ttl === null) {
121
            $expiration = static::EXPIRATION_INFINITY;
122
        } elseif ($ttl <= 0) {
123 17
            $expiration = -1;
124
        } else {
125
            $expiration = $ttl + time();
126
        }
127
128
        return $expiration;
129
    }
130
131
    /**
132
     * Normalizes cache TTL handling `null` value and {@see DateInterval} objects.
133
     * @param int|DateInterval|null $ttl raw TTL.
134
     * @return int|null TTL value as UNIX timestamp or null meaning infinity
135
     */
136
    protected function normalizeTtl($ttl): ?int
137
    {
138
        if ($ttl instanceof DateInterval) {
139
            try {
140
                return (new DateTime('@0'))->add($ttl)->getTimestamp();
141
            } catch (Exception $e) {
142
                return null;
143
            }
144
        }
145
146
        return $ttl;
147
    }
148
149
    /**
150
     * Converts iterable to array
151
     * @param iterable $iterable
152
     * @return array
153
     */
154
    protected function iterableToArray(iterable $iterable): array
155
    {
156
        return $iterable instanceof \Traversable ? iterator_to_array($iterable) : (array)$iterable;
157
    }
158
}
159