Passed
Push — development ( 8f3e46...8433eb )
by Spuds
01:17 queued 31s
created

Predis::put()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 13
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 3
1
<?php
2
3
/**
4
 * This file contains functions that deal with getting and setting RedisD cache values.
5
 *
6
 * @package   ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
9
 *
10
 * @version 2.0 dev
11
 *
12
 */
13
14
namespace ElkArte\Cache\CacheMethod;
15
16
/**
17
 * Predis
18
 */
19
class Predis extends AbstractCacheMethod
20
{
21
	/** {@inheritdoc} */
22
	protected $title = 'Predis';
23
24
	/** @var \Predis Predis instance representing the connection to the Redis servers. */
0 ignored issues
show
Bug introduced by
The type Predis was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
	protected $obj;
26
27
	/** @var server */
0 ignored issues
show
Bug introduced by
The type ElkArte\Cache\CacheMethod\server was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
	protected $server = [];
29
30
	/**
31
	 * {@inheritdoc}
32
	 */
33
	public function __construct($options)
34
	{
35
	//	require_once(EXTDIR . '/predis/autoload.php');
36
37
		if ($this->isAvailable())
38
		{
39
			parent::__construct($options);
40
			$this->addServers();
41
		}
42
	}
43
44
	/**
45
	 * {@inheritdoc}
46
	 */
47
	public function isAvailable()
48
	{
49
		return class_exists('\Predis\Client');
50
	}
51
52
	/**
53
	 * Add Redis servers.
54
	 *
55
	 * Don't add servers if they already exist. Ideal for persistent connections.
56
	 *
57
	 * @return bool True if there are servers in the daemon, false if not.
58
	 */
59
	protected function addServers()
60
	{
61
		if (!empty($this->_options['servers']))
62
		{
63
			$server = reset($this->_options['servers']);
64
			$server = explode(':', trim($server));
65
			$server[0] = !empty($server[0]) ? $server[0] : 'localhost';
66
			$server[1] = !empty($server[1]) ? $server[1] : 6379;
67
68
			$params = [
69
				'scheme' => 'tcp',
70
				'host' => $server[0],
71
				'port' => $server[1],
72
			];
73
74
			try
75
			{
76
				$this->obj = new \Predis\Client($params);
0 ignored issues
show
Bug introduced by
The type Predis\Client was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
77
				$this->obj->connect();
78
				$this->server[] = "tcp://{$server[0]}:{$server[1]}";
79
			}
80
			catch (\Predis\Connection\ConnectionException $e)
0 ignored issues
show
Bug introduced by
The type Predis\Connection\ConnectionException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
81
			{
82
				// Clear the object, should we log an error here?
83
				$this->obj = null;
84
			}
85
		}
86
	}
87
88
	/**
89
	 * Get redis servers.
90
	 *
91
	 * @return array A list of servers in the daemon.
92
	 */
93
	protected function getServers()
94
	{
95
		return $this->server;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->server returns the type ElkArte\Cache\CacheMethod\server which is incompatible with the documented return type array.
Loading history...
96
	}
97
98
	/**
99
	 * Retrieves statistics about the cache.
100
	 *
101
	 * @return array An associative array containing the cache statistics.
102
	 *    The array has the following keys:
103
	 *      - curr_items: The number of items currently stored in the cache.
104
	 *      - get_hits: The number of successful cache hits.
105
	 *      - get_misses: The number of cache misses.
106
	 *      - curr_connections: The number of current open connections to the cache server.
107
	 *      - version: The version of the cache server.
108
	 *      - hit_rate: The cache hit rate as a decimal value with two decimal places.
109
	 *      - miss_rate: The cache miss rate as a decimal value with two decimal places.
110
	 *
111
	 * If the statistics cannot be obtained, an empty array is returned.
112
	 */
113
	public function getStats()
114
	{
115
		$results = [];
116
117
		$cache = $this->obj->info();
118
119
		if ($cache === false)
120
		{
121
			return $results;
122
		}
123
124
		$elapsed = max($cache['Server']['uptime_in_seconds'], 1) / 60;
125
		$cache['Stats']['tracking_total_keys'] = count($this->obj->keys('*'));
126
127
		$results['curr_items'] = comma_format($cache['Stats']['tracking_total_keys'] ?? 0, 0);
128
		$results['get_hits'] = comma_format($cache['Stats']['keyspace_hits'] ?? 0, 0);
129
		$results['get_misses'] = comma_format($cache['Stats']['keyspace_misses'] ?? 0, 0);
130
		$results['curr_connections'] = $cache['Server']['connected_clients'] ?? 0;
131
		$results['version'] = $cache['Server']['redis_version'] ?? '0.0.0';
132
		$results['hit_rate'] = sprintf("%.2f", $cache['keyspace_hits'] / $elapsed);
133
		$results['miss_rate'] = sprintf("%.2f", $cache['keyspace_misses'] / $elapsed);
134
135
		return $results;
136
	}
137
138
	/**
139
	 * {@inheritdoc}
140
	 */
141
	public function exists($key)
142
	{
143
		$this->get($key);
144
145
		return !$this->is_miss;
146
	}
147
148
	/**
149
	 * {@inheritdoc}
150
	 */
151
	public function get($key, $ttl = 120)
152
	{
153
		if (!is_object($this->obj))
154
		{
155
			return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the return type mandated by ElkArte\Cache\CacheMetho...eMethodInterface::get() of array|null.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
156
		}
157
158
		$result = $this->obj->get($key);
159
		$this->is_miss = $result == null;
160
161
		return $result;
162
	}
163
164
	/**
165
	 * {@inheritdoc}
166
	 */
167
	public function put($key, $value, $ttl = 120)
168
	{
169
		if (!is_object($this->obj))
170
		{
171
			return '';
172
		}
173
174
		if ($value === null)
175
		{
176
			$this->obj->del($key);
177
		}
178
179
		$this->obj->set($key, $value);
180
	}
181
182
	/**
183
	 * {@inheritdoc}
184
	 */
185
	public function clean($type = '')
186
	{
187
		if (!is_object($this->obj))
188
		{
189
			return '';
190
		}
191
192
		// Clear it out, really invalidate whats there
193
		$this->obj->flush();
194
	}
195
196
	/**
197
	 * {@inheritdoc}
198
	 */
199
	public function details()
200
	{
201
		if (!is_object($this->obj))
202
		{
203
			return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the return type mandated by ElkArte\Cache\CacheMetho...hodInterface::details() of string[].

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
204
		}
205
206
		$version = $this->obj->info()['Server'];
207
208
		return array(
209
			'title' => $this->title(),
210
			'version' => !empty($version['redis_version']) ? $version['redis_version'] : '0.0.0'
211
		);
212
	}
213
214
	/**
215
	 * Adds the settings to the settings page.
216
	 *
217
	 * Used by integrate_modify_cache_settings added in the title method
218
	 *
219
	 * @param array $config_vars
220
	 */
221
	public function settings(&$config_vars)
222
	{
223
		global $txt;
224
225
		$var = [
226
			'cache_servers_redis', $txt['cache_redis'], 'file', 'text', 30, 'cache_redis', 'force_div_id' => 'redis_cache_redis',
227
		];
228
229
		$serversmList = $this->getServers();
230
		$serversmList = empty($serversmList) ? [$txt['admin_search_results_none']] : $serversmList;
231
		$var['postinput'] = $txt['cache_redis_servers'] . implode('</li><li>', $serversmList) . '</li></ul>';
232
233
		$config_vars[] = $var;
234
	}
235
}
236