Source of file MemcachedDriver.php

Size: 3,606 Bytes - Last Modified: 2020-05-08T12:23:11-04:00

../src/Driver/MemcachedDriver.php

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
<?php declare(strict_types=1);
/**
 * Banker
 *
 * A Caching library implementing psr/cache (PSR 6) and psr/simple-cache (PSR 16)
 *
 * PHP version 7.4
 *
 * @package     Banker
 * @author      Timothy J. Warren <tim@timshomepage.net>
 * @copyright   2016 - 2020  Timothy J. Warren
 * @license     http://www.opensource.org/licenses/mit-license.html  MIT License
 * @version     3.1.0
 * @link        https://git.timshomepage.net/timw4mail/banker
 */
namespace Aviat\Banker\Driver;

use Aviat\Banker\Exception\CacheException;

use Memcached;
use MemcachedException;

/**
 * Memcached cache backend
 */
class MemcachedDriver extends AbstractDriver {

	/**
	 * @var Memcached
	 */
	private ?Memcached $conn;

	/**
	 * Driver for PHP Memcache extension
	 *
	 * @codeCoverageIgnore
	 * @param array $config
	 * @param array $options
	 * @throws CacheException
	 */
	public function __construct(
		array $config = ['host' => '127.0.0.1', 'port' => '11211'],
		array $options = []
	)
	{
		if ( ! class_exists('Memcached'))
		{
			throw new CacheException('Memcached driver requires memcached extension');
		}

		try
		{
			$this->conn = new Memcached();
			$this->conn->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
			$this->conn->addServer($config['host'], (int) $config['port']);

			if ( ! empty($options))
			{
				$this->conn->setOptions($options);
			}
		}
		catch (MemcachedException $e)
		{
			// Rewrite MemcachedException as a CacheException to
			// match the requirements of the interface
			throw new CacheException($e->getMessage(), $e->getCode(), $e);
		}
	}

	/**
	 * Disconnect from memcached server
	 * @codeCoverageIgnore
	 */
	public function __destruct()
	{
		$this->conn->quit();
	}

	/**
	 * See if a key currently exists in the cache
	 *
	 * @param string $key
	 * @return bool
	 */
	public function exists(string $key): bool
	{
		$this->conn->get($key);
		$resultFlag = $this->conn->getResultCode();

		return ($resultFlag !== Memcached::RES_NOTFOUND);
	}

	/**
	 * Get the value for the selected cache key
	 *
	 * @param string $key
	 * @return mixed
	 */
	public function get(string $key)
	{
		return $this->conn->get($key);
	}

	/**
	 * Retrieve a set of values by their cache key
	 *
	 * @param string[] $keys
	 * @return array
	 */
	public function getMultiple(array $keys = []): array
	{
		$response = $this->conn->getMulti($keys);
		return (is_array($response)) ? $response : [];
	}

	/**
	 * Set a cached value
	 *
	 * @param string $key
	 * @param mixed $value
	 * @param int $expires
	 * @return bool
	 */
	public function set(string $key, $value, ?int $expires = 0): bool
	{
		return $this->conn->set($key, $value, $expires);
	}

	/**
	 * Remove an item from the cache
	 *
	 * @param string $key
	 * @return boolean
	 */
	public function delete(string $key): bool
	{
		return $this->conn->delete($key);
	}

	/**
	 * Remove multiple items from the cache
	 *
	 * @param string[] $keys
	 * @return boolean
	 */
	public function deleteMultiple(array $keys = []): bool
	{
		$deleted = $this->conn->deleteMulti($keys);
		return ($keys <=> $deleted) === 0;
	}

	/**
	 * Empty the cache
	 *
	 * @return boolean
	 */
	public function flush(): bool
	{
		return $this->conn->flush();
	}

	/**
	 * Set the specified key to expire at the given time
	 *
	 * @param string $key
	 * @param int $expires
	 * @return boolean
	 */
	public function expiresAt(string $key, int $expires): bool
	{
		if ($this->exists($key))
		{
			return $this->conn->touch($key, $expires);
		}

		$this->getLogger()->log('warning','Tried to set expiration on a key that does not exist');

		return FALSE;
	}
}