- Created complete documentation in docs/ directory - Added PROJECT_OVERVIEW.md with feature highlights and getting started guide - Added ARCHITECTURE.md with system design and technical details - Added SECURITY.md with comprehensive security implementation guide - Added DEVELOPMENT.md with development workflows and best practices - Added DEPLOYMENT.md with production deployment instructions - Added API.md with complete REST API documentation - Added CONTRIBUTING.md with contribution guidelines - Added CHANGELOG.md with version history and migration notes - Reorganized all documentation files into docs/ directory for better organization - Updated README.md with proper documentation links and quick navigation - Enhanced project structure with professional documentation standards
312 lines
7.8 KiB
PHP
312 lines
7.8 KiB
PHP
<?php
|
|
/*******************************************************************************************************************
|
|
| Software Name : EasyStream
|
|
| Software Description : High End YouTube Clone Script with Videos, Shorts, Streams, Images, Audio, Documents, Blogs
|
|
| Software Author : (c) Sami Ahmed
|
|
|*******************************************************************************************************************
|
|
|
|
|
|*******************************************************************************************************************
|
|
| This source file is subject to the EasyStream Proprietary License Agreement.
|
|
|
|
|
| By using this software, you acknowledge having read this Agreement and agree to be bound thereby.
|
|
|*******************************************************************************************************************
|
|
| Copyright (c) 2025 Sami Ahmed. All rights reserved.
|
|
|*******************************************************************************************************************/
|
|
|
|
defined('_ISVALID') or header('Location: /error');
|
|
|
|
/**
|
|
* Redis Connection and Management Class
|
|
*/
|
|
class VRedis
|
|
{
|
|
private static $instance = null;
|
|
private $redis = null;
|
|
private $connected = false;
|
|
|
|
public static function getInstance()
|
|
{
|
|
if (self::$instance === null) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
private function __construct()
|
|
{
|
|
$this->connect();
|
|
}
|
|
|
|
/**
|
|
* Connect to Redis server
|
|
*/
|
|
private function connect()
|
|
{
|
|
if (!extension_loaded('redis')) {
|
|
error_log('Redis extension not loaded');
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
$this->redis = new Redis();
|
|
|
|
$host = getenv('REDIS_HOST') ?: 'localhost';
|
|
$port = (int)(getenv('REDIS_PORT') ?: 6379);
|
|
$timeout = 5;
|
|
|
|
$this->connected = $this->redis->connect($host, $port, $timeout);
|
|
|
|
if ($this->connected) {
|
|
// Set connection options
|
|
$this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_JSON);
|
|
$this->redis->setOption(Redis::OPT_PREFIX, 'easystream:');
|
|
|
|
// Test connection
|
|
$this->redis->ping();
|
|
|
|
VLogger::getInstance()->info('Redis connected successfully', [
|
|
'host' => $host,
|
|
'port' => $port
|
|
]);
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
$this->connected = false;
|
|
error_log('Redis connection failed: ' . $e->getMessage());
|
|
VLogger::getInstance()->error('Redis connection failed', [
|
|
'error' => $e->getMessage(),
|
|
'host' => $host ?? 'unknown',
|
|
'port' => $port ?? 6379
|
|
]);
|
|
}
|
|
|
|
return $this->connected;
|
|
}
|
|
|
|
/**
|
|
* Check if Redis is connected
|
|
*/
|
|
public function isConnected()
|
|
{
|
|
return $this->connected && $this->redis !== null;
|
|
}
|
|
|
|
/**
|
|
* Get Redis instance
|
|
*/
|
|
public function getRedis()
|
|
{
|
|
if (!$this->isConnected()) {
|
|
$this->connect();
|
|
}
|
|
return $this->redis;
|
|
}
|
|
|
|
/**
|
|
* Set a key-value pair
|
|
*/
|
|
public function set($key, $value, $ttl = null)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
if ($ttl !== null) {
|
|
return $this->redis->setex($key, $ttl, $value);
|
|
} else {
|
|
return $this->redis->set($key, $value);
|
|
}
|
|
} catch (Exception $e) {
|
|
error_log('Redis SET error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a value by key
|
|
*/
|
|
public function get($key)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
return $this->redis->get($key);
|
|
} catch (Exception $e) {
|
|
error_log('Redis GET error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a key
|
|
*/
|
|
public function delete($key)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
return $this->redis->del($key);
|
|
} catch (Exception $e) {
|
|
error_log('Redis DELETE error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if key exists
|
|
*/
|
|
public function exists($key)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
return $this->redis->exists($key);
|
|
} catch (Exception $e) {
|
|
error_log('Redis EXISTS error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set expiration for a key
|
|
*/
|
|
public function expire($key, $ttl)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
return $this->redis->expire($key, $ttl);
|
|
} catch (Exception $e) {
|
|
error_log('Redis EXPIRE error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Push to list (queue)
|
|
*/
|
|
public function lpush($key, $value)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
return $this->redis->lpush($key, $value);
|
|
} catch (Exception $e) {
|
|
error_log('Redis LPUSH error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pop from list (queue) - blocking
|
|
*/
|
|
public function brpop($keys, $timeout = 0)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
return $this->redis->brpop($keys, $timeout);
|
|
} catch (Exception $e) {
|
|
error_log('Redis BRPOP error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get list length
|
|
*/
|
|
public function llen($key)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return 0;
|
|
}
|
|
|
|
try {
|
|
return $this->redis->llen($key);
|
|
} catch (Exception $e) {
|
|
error_log('Redis LLEN error: ' . $e->getMessage());
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Increment counter
|
|
*/
|
|
public function incr($key)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
return $this->redis->incr($key);
|
|
} catch (Exception $e) {
|
|
error_log('Redis INCR error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Decrement counter
|
|
*/
|
|
public function decr($key)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
return $this->redis->decr($key);
|
|
} catch (Exception $e) {
|
|
error_log('Redis DECR error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Redis info
|
|
*/
|
|
public function info($section = null)
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return [];
|
|
}
|
|
|
|
try {
|
|
return $this->redis->info($section);
|
|
} catch (Exception $e) {
|
|
error_log('Redis INFO error: ' . $e->getMessage());
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Flush all data (use with caution)
|
|
*/
|
|
public function flushAll()
|
|
{
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
return $this->redis->flushAll();
|
|
} catch (Exception $e) {
|
|
error_log('Redis FLUSHALL error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
} |