<commit_before><?php

namespace Rhymix\Framework\Drivers\Cache;

/**
 * The Redis cache driver.
 */
class Redis implements \Rhymix\Framework\Drivers\CacheInterface
{
	/**
	 * Set this flag to false to disable cache prefixes.
	 */
	public $prefix = true;
	
	/**
	 * The singleton instance is stored here.
	 */
	protected static $_instance = null;
	
	/**
	 * The Redis connection is stored here.
	 */
	protected $_conn = null;
	
	/**
	 * Direct invocation of the constructor is not permitted.
	 */
	protected function __construct(array $config)
	{
		try
		{
			$this->_conn = null;
			foreach ($config as $url)
			{
				$info = parse_url($url);
				if (isset($info['host']) && isset($info['port']))
				{
					$this->_conn = new \Redis;
					$this->_conn->connect($info['host'], $info['port'], 0.15);
					if(isset($info['user']) || isset($info['pass']))
					{
						$this->_conn->auth(isset($info['user']) ? $info['user'] : $info['pass']);
					}
					if(isset($info['path']) && $dbnum = intval(substr($info['path'], 1)))
					{
						$this->_conn->select($dbnum);
					}
					break;
				}
			}
		}
		catch (\RedisException $e)
		{
			$this->_conn = null;
		}
	}
	
	/**
	 * Create a new instance of the current cache driver, using the given settings.
	 * 
	 * @param array $config
	 * @return void
	 */
	public static function getInstance(array $config)
	{
		if (self::$_instance === null)
		{
			self::$_instance = new self($config);
		}
		return self::$_instance;
	}
	
	/**
	 * Check if the current cache driver is supported on this server.
	 * 
	 * This method returns true on success and false on failure.
	 * 
	 * @return bool
	 */
	public static function isSupported()
	{
		return class_exists('\\Redis', false);
	}
	
	/**
	 * Validate cache settings.
	 * 
	 * This method returns true on success and false on failure.
	 * 
	 * @param mixed $config
	 * @return bool
	 */
	public static function validateSettings($config)
	{
		try
		{
			$conn = new \Redis;
			foreach ($config as $url)
			{
				$info = parse_url($url);
				if (isset($info['host']) && isset($info['port']))
				{
					$conn->connect($info['host'], $info['port'], 0.15);
					if(isset($info['user']) || isset($info['pass']))
					{
						$conn->auth(isset($info['user']) ? $info['user'] : $info['pass']);
					}
					if(isset($info['path']) && $dbnum = intval(substr($info['path'], 1)))
					{
						$conn->select($dbnum);
					}
					return true;
				}
			}
			return false;
		}
		catch (\RedisException $e)
		{
			return false;
		}
	}
	
	/**
	 * Get the value of a key.
	 * 
	 * This method returns null if the key was not found.
	 * 
	 * @param string $key
	 * @return mixed
	 */
	public function get($key)
	{
		try
		{
			$value = $this->_conn->get($key);
		}
		catch (\RedisException $e)
		{
			return null;
		}
		
		if ($value === false)
		{
			return null;
		}
		
		$value = unserialize($value);
		if ($value === false)
		{
			return null;
		}
		return $value;
	}
	
	/**
	 * Set the value to a key.
	 * 
	 * This method returns true on success and false on failure.
	 * $ttl is measured in seconds. If it is zero, the key should not expire.
	 * 
	 * @param string $key
	 * @param mixed $value
	 * @param int $ttl
	 * @param bool $force
	 * @return bool
	 */
	public function set($key, $value, $ttl = 0, $force = false)
	{
		try
		{
			return $this->_conn->setex($key, $ttl, serialize($value)) ? true : false;
		}
		catch (\RedisException $e)
		{
			return false;
		}
	}
	
	/**
	 * Delete a key.
	 * 
	 * This method returns true on success and false on failure.
	 * If the key does not exist, it should return false.
	 * <commit_msg>Fix #621 incorrect incr/decr of key group versions in Redis cache<commit_after><?php

namespace Rhymix\Framework\Drivers\Cache;

/**
 * The Redis cache driver.
 */
class Redis implements \Rhymix\Framework\Drivers\CacheInterface
{
	/**
	 * Set this flag to false to disable cache prefixes.
	 */
	public $prefix = true;
	
	/**
	 * The singleton instance is stored here.
	 */
	protected static $_instance = null;
	
	/**
	 * The Redis connection is stored here.
	 */
	protected $_conn = null;
	
	/**
	 * Direct invocation of the constructor is not permitted.
	 */
	protected function __construct(array $config)
	{
		try
		{
			$this->_conn = null;
			foreach ($config as $url)
			{
				$info = parse_url($url);
				if (isset($info['host']) && isset($info['port']))
				{
					$this->_conn = new \Redis;
					$this->_conn->connect($info['host'], $info['port'], 0.15);
					if(isset($info['user']) || isset($info['pass']))
					{
						$this->_conn->auth(isset($info['user']) ? $info['user'] : $info['pass']);
					}
					if(isset($info['path']) && $dbnum = intval(substr($info['path'], 1)))
					{
						$this->_conn->select($dbnum);
					}
					break;
				}
			}
		}
		catch (\RedisException $e)
		{
			$this->_conn = null;
		}
	}
	
	/**
	 * Create a new instance of the current cache driver, using the given settings.
	 * 
	 * @param array $config
	 * @return void
	 */
	public static function getInstance(array $config)
	{
		if (self::$_instance === null)
		{
			self::$_instance = new self($config);
		}
		return self::$_instance;
	}
	
	/**
	 * Check if the current cache driver is supported on this server.
	 * 
	 * This method returns true on success and false on failure.
	 * 
	 * @return bool
	 */
	public static function isSupported()
	{
		return class_exists('\\Redis', false);
	}
	
	/**
	 * Validate cache settings.
	 * 
	 * This method returns true on success and false on failure.
	 * 
	 * @param mixed $config
	 * @return bool
	 */
	public static function validateSettings($config)
	{
		try
		{
			$conn = new \Redis;
			foreach ($config as $url)
			{
				$info = parse_url($url);
				if (isset($info['host']) && isset($info['port']))
				{
					$conn->connect($info['host'], $info['port'], 0.15);
					if(isset($info['user']) || isset($info['pass']))
					{
						$conn->auth(isset($info['user']) ? $info['user'] : $info['pass']);
					}
					if(isset($info['path']) && $dbnum = intval(substr($info['path'], 1)))
					{
						$conn->select($dbnum);
					}
					return true;
				}
			}
			return false;
		}
		catch (\RedisException $e)
		{
			return false;
		}
	}
	
	/**
	 * Get the value of a key.
	 * 
	 * This method returns null if the key was not found.
	 * 
	 * @param string $key
	 * @return mixed
	 */
	public function get($key)
	{
		try
		{
			$value = $this->_conn->get($key);
		}
		catch (\RedisException $e)
		{
			return null;
		}
		
		if ($value === false)
		{
			return null;
		}
		if (ctype_digit($value))
		{
			return $value;
		}
		
		$value = unserialize($value);
		if ($value === false)
		{
			return null;
		}
		return $value;
	}
	
	/**
	 * Set the value to a key.
	 * 
	 * This method returns true on success and false on failure.
	 * $ttl is measured in seconds. If it is zero, the key should not expire.
	 * 
	 * @param string $key
	 * @param mixed $value
	 * @param int $ttl
	 * @param bool $force
	 * @return bool
	 */
	public function set($key, $value, $ttl = 0, $force = false)
	{
		try
		{
			$value = (is_scalar($value) && ctype_digit($value)) ? $value : serialize($value);
			return $this->_conn->setex($key, $ttl, $value) ? true : false;
		}
		catch (\RedisException $e)
		{
			return false;
		}
	}
	
	/**
	 * Delete a key.
	 * 
	 * This method returns true on success and false on failure.
	 * If the key does not exist, it should return false.
	 * 
{'fraction_non_alphanumeric': 0.165878697825206, 'fraction_numerical': 0.002836687829258409, 'mean_word_length': 2.6599110232328225, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2387501', 'n_tokens_mistral': 2989, 'n_tokens_neox': 2427, 'n_words': 697}