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:
SamiAhmed7777
2025-10-21 00:39:45 -07:00
commit 0b7e2d0a5b
6080 changed files with 1332936 additions and 0 deletions

View File

@@ -0,0 +1,332 @@
<?php
/*******************************************************************************************************************
| Example: Queue System Integration
| This file demonstrates how to integrate the queue system into your EasyStream application
|*******************************************************************************************************************/
define('_ISVALID', true);
include_once 'f_core/config.core.php';
// Example 1: User Registration with Welcome Email
function handleUserRegistration($userData) {
global $class_database;
// Save user to database
$userId = $class_database->doInsert('db_accountuser', $userData);
if ($userId) {
// Enqueue welcome email (runs in background)
enqueue_welcome_email(
$userId,
$userData['usr_email'],
$userData['usr_user']
);
// Enqueue welcome notification
enqueue_notification(
$userId,
'welcome',
'Welcome to EasyStream! Start by uploading your first video.',
'Welcome to EasyStream!'
);
return $userId;
}
return false;
}
// Example 2: Video Upload Processing
function handleVideoUpload($videoData, $uploadedFile) {
global $class_database;
// Save video metadata to database
$videoId = $class_database->doInsert('db_videofiles', $videoData);
if ($videoId) {
// Move uploaded file to processing directory
$processingDir = 'f_data/data_userfiles/processing/';
$inputFile = $processingDir . $videoId . '_original.mp4';
$outputDir = 'f_data/data_userfiles/user_media/' . $videoData['usr_id'] . '/v/';
if (move_uploaded_file($uploadedFile['tmp_name'], $inputFile)) {
// Enqueue video processing job
$jobId = enqueue_video_processing(
$videoId,
$inputFile,
$outputDir,
['1080p', '720p', '480p', '360p']
);
// Notify user that upload is complete and processing started
enqueue_video_upload_notification(
$videoData['usr_id'],
$videoData['file_title'],
'/watch/' . $videoId
);
VLogger::getInstance()->info('Video upload queued for processing', [
'video_id' => $videoId,
'job_id' => $jobId,
'user_id' => $videoData['usr_id']
]);
return $videoId;
}
}
return false;
}
// Example 3: Password Reset Request
function handlePasswordResetRequest($email) {
global $class_database;
// Check if user exists
$user = $class_database->singleFieldValue('db_accountuser', 'usr_id', 'usr_email', $email);
if ($user) {
// Generate reset token
$resetToken = bin2hex(random_bytes(32));
$resetUrl = 'https://yourdomain.com/reset-password?token=' . $resetToken;
// Store reset token in database
$resetData = [
'usr_id' => $user,
'reset_token' => $resetToken,
'expires_at' => date('Y-m-d H:i:s', time() + 86400), // 24 hours
'created_at' => date('Y-m-d H:i:s')
];
$class_database->doInsert('db_password_resets', $resetData);
// Enqueue password reset email
enqueue_password_reset_email($email, $resetToken, $resetUrl);
return true;
}
return false;
}
// Example 4: Bulk Notification to Subscribers
function notifySubscribersOfNewVideo($channelId, $videoId, $videoTitle) {
global $class_database, $db;
// Get all subscribers of the channel
$sql = "SELECT usr_id FROM db_subscriptions WHERE channel_id = ? AND active = 1";
$result = $db->Execute($sql, [$channelId]);
$jobs = [];
$videoUrl = '/watch/' . $videoId;
// Get channel name
$channelName = $class_database->singleFieldValue('db_accountuser', 'usr_user', 'usr_id', $channelId);
while ($result && !$result->EOF) {
$subscriberId = $result->fields['usr_id'];
// Prepare notification job for each subscriber
$jobs[] = [
'class' => 'SendNotificationJob',
'data' => [
'user_id' => $subscriberId,
'type' => 'new_video',
'message' => "{$channelName} has uploaded a new video: '{$videoTitle}'",
'title' => 'New Video from Subscription',
'action_url' => $videoUrl,
'metadata' => [
'channel_id' => $channelId,
'channel_name' => $channelName,
'video_id' => $videoId
]
]
];
$result->MoveNext();
}
// Enqueue all notification jobs as a batch
if (!empty($jobs)) {
$jobIds = enqueue_batch($jobs, 'notifications');
VLogger::getInstance()->info('Subscriber notifications enqueued', [
'channel_id' => $channelId,
'video_id' => $videoId,
'subscriber_count' => count($jobs),
'job_count' => count($jobIds)
]);
return count($jobIds);
}
return 0;
}
// Example 5: Scheduled Content Publishing
function scheduleContentPublishing($contentId, $publishDate) {
$delay = strtotime($publishDate) - time();
if ($delay > 0) {
// Schedule the job to run at the specified time
$jobId = enqueue_job('PublishContentJob', [
'content_id' => $contentId,
'publish_date' => $publishDate
], 'default', $delay);
VLogger::getInstance()->info('Content publishing scheduled', [
'content_id' => $contentId,
'publish_date' => $publishDate,
'delay_seconds' => $delay,
'job_id' => $jobId
]);
return $jobId;
}
return false;
}
// Example 6: Daily Statistics Report
function scheduleDailyReports() {
// Calculate delay until next midnight
$tomorrow = strtotime('tomorrow midnight');
$delay = $tomorrow - time();
// Schedule daily report generation
$jobId = enqueue_job('GenerateDailyReportJob', [
'report_date' => date('Y-m-d'),
'recipients' => ['admin@easystream.com', 'analytics@easystream.com']
], 'default', $delay);
return $jobId;
}
// Example 7: Video Processing Completion Handler
function handleVideoProcessingComplete($videoId, $success, $results) {
global $class_database;
// Get video and user info
$video = $class_database->singleFieldValue('db_videofiles', '*', 'file_key', $videoId);
if ($video) {
// Update video status
$updateData = [
'processing_status' => $success ? 'completed' : 'failed',
'processed_at' => date('Y-m-d H:i:s')
];
$class_database->doUpdate('db_videofiles', 'file_key', $updateData, $videoId);
// Notify user of processing completion
enqueue_video_processing_notification(
$video['usr_id'],
$video['file_title'],
'/watch/' . $videoId,
$success
);
// If successful, notify subscribers
if ($success) {
notifySubscribersOfNewVideo(
$video['usr_id'],
$videoId,
$video['file_title']
);
}
}
}
// Example 8: Cleanup Old Jobs (can be run via cron)
function cleanupOldJobs() {
$redis = VRedis::getInstance();
if (!$redis->isConnected()) {
return false;
}
try {
$redisInstance = $redis->getRedis();
$jobKeys = $redisInstance->keys('job:*');
$cleaned = 0;
$cutoffTime = time() - (7 * 24 * 3600); // 7 days ago
foreach ($jobKeys as $jobKey) {
$job = $redis->get(str_replace('easystream:', '', $jobKey));
if ($job && isset($job['created_at']) && $job['created_at'] < $cutoffTime) {
// Only clean completed or failed jobs
if (in_array($job['status'], ['completed', 'failed'])) {
$redis->delete(str_replace('easystream:', '', $jobKey));
$cleaned++;
}
}
}
VLogger::getInstance()->info('Old jobs cleaned up', [
'cleaned_count' => $cleaned,
'cutoff_time' => date('Y-m-d H:i:s', $cutoffTime)
]);
return $cleaned;
} catch (Exception $e) {
VLogger::getInstance()->error('Job cleanup failed', [
'error' => $e->getMessage()
]);
return false;
}
}
// Example usage in your existing code:
// In your user registration handler:
if ($_POST['action'] === 'register') {
$userData = [
'usr_user' => VSecurity::postParam('username', 'alphanum'),
'usr_email' => VSecurity::postParam('email', 'email'),
'usr_password' => password_hash(VSecurity::postParam('password', 'string'), PASSWORD_DEFAULT),
'usr_datereg' => date('Y-m-d H:i:s')
];
$userId = handleUserRegistration($userData);
if ($userId) {
echo json_encode(['success' => true, 'user_id' => $userId]);
} else {
echo json_encode(['success' => false, 'error' => 'Registration failed']);
}
}
// In your video upload handler:
if ($_POST['action'] === 'upload_video' && isset($_FILES['video'])) {
$videoData = [
'usr_id' => $_SESSION['USER_ID'],
'file_title' => VSecurity::postParam('title', 'string'),
'file_description' => VSecurity::postParam('description', 'html'),
'upload_date' => date('Y-m-d H:i:s'),
'processing_status' => 'pending'
];
$videoId = handleVideoUpload($videoData, $_FILES['video']);
if ($videoId) {
echo json_encode(['success' => true, 'video_id' => $videoId]);
} else {
echo json_encode(['success' => false, 'error' => 'Upload failed']);
}
}
// In your password reset handler:
if ($_POST['action'] === 'reset_password') {
$email = VSecurity::postParam('email', 'email');
if (handlePasswordResetRequest($email)) {
echo json_encode(['success' => true, 'message' => 'Reset email sent']);
} else {
echo json_encode(['success' => false, 'error' => 'Email not found']);
}
}
echo "Queue integration examples completed. Check the queue management interface for job status.";
?>