feat: Add comprehensive documentation suite and reorganize project structure
- 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
This commit is contained in:
@@ -0,0 +1,356 @@
|
||||
<?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');
|
||||
|
||||
/**
|
||||
* Global Error Handler for comprehensive error tracking
|
||||
*/
|
||||
class VErrorHandler
|
||||
{
|
||||
private static $instance = null;
|
||||
private $logger;
|
||||
private $isProduction = true;
|
||||
|
||||
public static function getInstance()
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
$this->logger = VLogger::getInstance();
|
||||
|
||||
// Determine if we're in production mode
|
||||
global $cfg;
|
||||
$this->isProduction = !isset($cfg['debug_mode']) || !$cfg['debug_mode'];
|
||||
|
||||
// Register error handlers
|
||||
$this->registerHandlers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all error handlers
|
||||
*/
|
||||
private function registerHandlers()
|
||||
{
|
||||
// Set error handler for PHP errors
|
||||
set_error_handler([$this, 'handleError']);
|
||||
|
||||
// Set exception handler for uncaught exceptions
|
||||
set_exception_handler([$this, 'handleException']);
|
||||
|
||||
// Set shutdown handler for fatal errors
|
||||
register_shutdown_function([$this, 'handleShutdown']);
|
||||
|
||||
// Set error reporting level
|
||||
if ($this->isProduction) {
|
||||
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT);
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('log_errors', 1);
|
||||
} else {
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle PHP errors
|
||||
*/
|
||||
public function handleError($severity, $message, $file, $line, $context = [])
|
||||
{
|
||||
// Don't handle errors that are suppressed with @
|
||||
if (!(error_reporting() & $severity)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$errorType = $this->getErrorType($severity);
|
||||
$logLevel = $this->getLogLevel($severity);
|
||||
|
||||
$errorContext = [
|
||||
'error_type' => $errorType,
|
||||
'severity' => $severity,
|
||||
'file' => $file,
|
||||
'line' => $line,
|
||||
'context' => $context
|
||||
];
|
||||
|
||||
$errorMessage = "{$errorType}: {$message} in {$file} on line {$line}";
|
||||
|
||||
$this->logger->log($logLevel, $errorMessage, $errorContext);
|
||||
|
||||
// Don't execute PHP internal error handler
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle uncaught exceptions
|
||||
*/
|
||||
public function handleException($exception)
|
||||
{
|
||||
$errorContext = [
|
||||
'exception_class' => get_class($exception),
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine(),
|
||||
'trace' => $exception->getTraceAsString(),
|
||||
'previous' => $exception->getPrevious() ? $exception->getPrevious()->getMessage() : null
|
||||
];
|
||||
|
||||
$errorMessage = "Uncaught Exception: " . $exception->getMessage() .
|
||||
" in " . $exception->getFile() . " on line " . $exception->getLine();
|
||||
|
||||
$this->logger->critical($errorMessage, $errorContext);
|
||||
|
||||
// Show user-friendly error page in production
|
||||
if ($this->isProduction) {
|
||||
$this->showErrorPage('An unexpected error occurred. Please try again later.');
|
||||
} else {
|
||||
$this->showDebugError($exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle fatal errors during shutdown
|
||||
*/
|
||||
public function handleShutdown()
|
||||
{
|
||||
$error = error_get_last();
|
||||
|
||||
if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
|
||||
$errorType = $this->getErrorType($error['type']);
|
||||
|
||||
$errorContext = [
|
||||
'error_type' => $errorType,
|
||||
'severity' => $error['type'],
|
||||
'file' => $error['file'],
|
||||
'line' => $error['line']
|
||||
];
|
||||
|
||||
$errorMessage = "Fatal Error: {$error['message']} in {$error['file']} on line {$error['line']}";
|
||||
|
||||
$this->logger->critical($errorMessage, $errorContext);
|
||||
|
||||
// Show error page for fatal errors
|
||||
if ($this->isProduction) {
|
||||
$this->showErrorPage('A critical error occurred. Please contact support.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error type string from severity level
|
||||
*/
|
||||
private function getErrorType($severity)
|
||||
{
|
||||
$errorTypes = [
|
||||
E_ERROR => 'Fatal Error',
|
||||
E_WARNING => 'Warning',
|
||||
E_PARSE => 'Parse Error',
|
||||
E_NOTICE => 'Notice',
|
||||
E_CORE_ERROR => 'Core Error',
|
||||
E_CORE_WARNING => 'Core Warning',
|
||||
E_COMPILE_ERROR => 'Compile Error',
|
||||
E_COMPILE_WARNING => 'Compile Warning',
|
||||
E_USER_ERROR => 'User Error',
|
||||
E_USER_WARNING => 'User Warning',
|
||||
E_USER_NOTICE => 'User Notice',
|
||||
E_STRICT => 'Strict Standards',
|
||||
E_RECOVERABLE_ERROR => 'Recoverable Error',
|
||||
E_DEPRECATED => 'Deprecated',
|
||||
E_USER_DEPRECATED => 'User Deprecated'
|
||||
];
|
||||
|
||||
return $errorTypes[$severity] ?? 'Unknown Error';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get log level from error severity
|
||||
*/
|
||||
private function getLogLevel($severity)
|
||||
{
|
||||
switch ($severity) {
|
||||
case E_ERROR:
|
||||
case E_PARSE:
|
||||
case E_CORE_ERROR:
|
||||
case E_COMPILE_ERROR:
|
||||
case E_USER_ERROR:
|
||||
case E_RECOVERABLE_ERROR:
|
||||
return VLogger::ERROR;
|
||||
|
||||
case E_WARNING:
|
||||
case E_CORE_WARNING:
|
||||
case E_COMPILE_WARNING:
|
||||
case E_USER_WARNING:
|
||||
return VLogger::WARNING;
|
||||
|
||||
case E_NOTICE:
|
||||
case E_USER_NOTICE:
|
||||
case E_STRICT:
|
||||
return VLogger::NOTICE;
|
||||
|
||||
case E_DEPRECATED:
|
||||
case E_USER_DEPRECATED:
|
||||
return VLogger::INFO;
|
||||
|
||||
default:
|
||||
return VLogger::ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show user-friendly error page
|
||||
*/
|
||||
private function showErrorPage($message)
|
||||
{
|
||||
// Clear any output buffer
|
||||
if (ob_get_level()) {
|
||||
ob_clean();
|
||||
}
|
||||
|
||||
http_response_code(500);
|
||||
|
||||
// Try to use existing error template
|
||||
if (file_exists('error.php')) {
|
||||
include 'error.php';
|
||||
} else {
|
||||
// Fallback error page
|
||||
echo $this->getErrorPageHTML($message);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show debug error information
|
||||
*/
|
||||
private function showDebugError($exception)
|
||||
{
|
||||
if (ob_get_level()) {
|
||||
ob_clean();
|
||||
}
|
||||
|
||||
http_response_code(500);
|
||||
|
||||
echo $this->getDebugErrorHTML($exception);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error page HTML
|
||||
*/
|
||||
private function getErrorPageHTML($message)
|
||||
{
|
||||
return '<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Error - EasyStream</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
|
||||
.error-container { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); max-width: 600px; margin: 0 auto; }
|
||||
.error-title { color: #d32f2f; font-size: 24px; margin-bottom: 20px; }
|
||||
.error-message { color: #666; line-height: 1.6; }
|
||||
.error-actions { margin-top: 30px; }
|
||||
.btn { background: #1976d2; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px; display: inline-block; }
|
||||
.btn:hover { background: #1565c0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="error-container">
|
||||
<h1 class="error-title">Oops! Something went wrong</h1>
|
||||
<p class="error-message">' . htmlspecialchars($message) . '</p>
|
||||
<div class="error-actions">
|
||||
<a href="/" class="btn">Go Home</a>
|
||||
<a href="javascript:history.back()" class="btn" style="background: #666; margin-left: 10px;">Go Back</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get debug error HTML
|
||||
*/
|
||||
private function getDebugErrorHTML($exception)
|
||||
{
|
||||
$trace = $exception->getTraceAsString();
|
||||
|
||||
return '<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Debug Error - EasyStream</title>
|
||||
<style>
|
||||
body { font-family: monospace; margin: 20px; background: #1e1e1e; color: #fff; }
|
||||
.error-header { background: #d32f2f; padding: 15px; margin-bottom: 20px; border-radius: 4px; }
|
||||
.error-details { background: #2d2d2d; padding: 15px; border-radius: 4px; margin-bottom: 20px; }
|
||||
.trace { background: #1a1a1a; padding: 15px; border-radius: 4px; overflow-x: auto; }
|
||||
pre { margin: 0; white-space: pre-wrap; }
|
||||
.file-line { color: #ffeb3b; }
|
||||
.message { color: #f44336; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="error-header">
|
||||
<h1>Exception: ' . htmlspecialchars(get_class($exception)) . '</h1>
|
||||
</div>
|
||||
|
||||
<div class="error-details">
|
||||
<p><strong>Message:</strong> <span class="message">' . htmlspecialchars($exception->getMessage()) . '</span></p>
|
||||
<p><strong>File:</strong> <span class="file-line">' . htmlspecialchars($exception->getFile()) . ':' . $exception->getLine() . '</span></p>
|
||||
</div>
|
||||
|
||||
<div class="trace">
|
||||
<h3>Stack Trace:</h3>
|
||||
<pre>' . htmlspecialchars($trace) . '</pre>
|
||||
</div>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Log custom application errors
|
||||
*/
|
||||
public function logApplicationError($message, $context = [])
|
||||
{
|
||||
$this->logger->error('Application Error: ' . $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log validation errors
|
||||
*/
|
||||
public function logValidationError($field, $value, $rule, $context = [])
|
||||
{
|
||||
$message = "Validation failed for field '{$field}' with value '{$value}' against rule '{$rule}'";
|
||||
$this->logger->warning($message, array_merge($context, [
|
||||
'validation_error' => true,
|
||||
'field' => $field,
|
||||
'value' => $value,
|
||||
'rule' => $rule
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Log authentication errors
|
||||
*/
|
||||
public function logAuthError($message, $username = null, $context = [])
|
||||
{
|
||||
$this->logger->warning('Authentication Error: ' . $message, array_merge($context, [
|
||||
'auth_error' => true,
|
||||
'username' => $username
|
||||
]));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user