- 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
477 lines
13 KiB
PHP
477 lines
13 KiB
PHP
<?php
|
|
/*******************************************************************************************************************
|
|
| EasyStream Production Setup Script
|
|
| Sets up the platform for production deployment
|
|
|*******************************************************************************************************************/
|
|
|
|
define('_ISVALID', true);
|
|
|
|
// Include core configuration
|
|
include_once 'f_core/config.core.php';
|
|
|
|
/**
|
|
* Production Setup Manager
|
|
*/
|
|
class ProductionSetup
|
|
{
|
|
private $logger;
|
|
private $db;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->logger = VLogger::getInstance();
|
|
$this->db = VDatabase::getInstance();
|
|
}
|
|
|
|
/**
|
|
* Run complete production setup
|
|
*/
|
|
public function setup()
|
|
{
|
|
echo "EasyStream Production Setup\n";
|
|
echo str_repeat("=", 40) . "\n\n";
|
|
|
|
$steps = [
|
|
'checkRequirements' => 'Checking system requirements',
|
|
'createDirectories' => 'Creating required directories',
|
|
'setupDatabase' => 'Setting up database tables',
|
|
'configurePermissions' => 'Configuring file permissions',
|
|
'setupCronJobs' => 'Setting up cron jobs',
|
|
'testComponents' => 'Testing core components',
|
|
'generateConfig' => 'Generating production config'
|
|
];
|
|
|
|
$totalSteps = count($steps);
|
|
$currentStep = 0;
|
|
|
|
foreach ($steps as $method => $description) {
|
|
$currentStep++;
|
|
echo "[{$currentStep}/{$totalSteps}] {$description}...\n";
|
|
|
|
try {
|
|
$result = $this->$method();
|
|
|
|
if ($result['success']) {
|
|
echo " ✓ " . $result['message'] . "\n";
|
|
} else {
|
|
echo " ✗ " . $result['message'] . "\n";
|
|
if (isset($result['details'])) {
|
|
foreach ($result['details'] as $detail) {
|
|
echo " - {$detail}\n";
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception $e) {
|
|
echo " ✗ Error: " . $e->getMessage() . "\n";
|
|
}
|
|
|
|
echo "\n";
|
|
}
|
|
|
|
echo "Production setup completed!\n\n";
|
|
echo "Next steps:\n";
|
|
echo "1. Start queue workers: php start-workers.php\n";
|
|
echo "2. Monitor system: php f_core/f_workers/queue-monitor.php monitor\n";
|
|
echo "3. Check logs in: logs/\n\n";
|
|
}
|
|
|
|
/**
|
|
* Check system requirements
|
|
*/
|
|
private function checkRequirements()
|
|
{
|
|
$requirements = [
|
|
'PHP version >= 8.0' => version_compare(PHP_VERSION, '8.0.0', '>='),
|
|
'FFmpeg installed' => $this->checkFFmpeg(),
|
|
'Redis available' => $this->checkRedis(),
|
|
'Database connection' => $this->checkDatabase(),
|
|
'GD extension' => extension_loaded('gd'),
|
|
'JSON extension' => extension_loaded('json'),
|
|
'cURL extension' => extension_loaded('curl'),
|
|
'OpenSSL extension' => extension_loaded('openssl')
|
|
];
|
|
|
|
$passed = 0;
|
|
$failed = [];
|
|
|
|
foreach ($requirements as $requirement => $status) {
|
|
if ($status) {
|
|
$passed++;
|
|
} else {
|
|
$failed[] = $requirement;
|
|
}
|
|
}
|
|
|
|
if (empty($failed)) {
|
|
return [
|
|
'success' => true,
|
|
'message' => "All {$passed} requirements met"
|
|
];
|
|
} else {
|
|
return [
|
|
'success' => false,
|
|
'message' => count($failed) . ' requirements failed',
|
|
'details' => $failed
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create required directories
|
|
*/
|
|
private function createDirectories()
|
|
{
|
|
$directories = [
|
|
'f_data/temp',
|
|
'f_data/processed',
|
|
'f_data/media',
|
|
'f_data/thumbnails',
|
|
'f_data/logs',
|
|
'logs'
|
|
];
|
|
|
|
$created = 0;
|
|
$errors = [];
|
|
|
|
foreach ($directories as $dir) {
|
|
$fullPath = _FPATH . $dir;
|
|
|
|
if (!is_dir($fullPath)) {
|
|
if (mkdir($fullPath, 0755, true)) {
|
|
$created++;
|
|
} else {
|
|
$errors[] = "Failed to create: {$dir}";
|
|
}
|
|
}
|
|
}
|
|
|
|
if (empty($errors)) {
|
|
return [
|
|
'success' => true,
|
|
'message' => "Created {$created} directories"
|
|
];
|
|
} else {
|
|
return [
|
|
'success' => false,
|
|
'message' => 'Directory creation failed',
|
|
'details' => $errors
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Setup database tables
|
|
*/
|
|
private function setupDatabase()
|
|
{
|
|
try {
|
|
// Check if new tables exist
|
|
$newTables = [
|
|
'db_votes',
|
|
'db_comments',
|
|
'db_social_shares',
|
|
'db_video_views',
|
|
'db_video_analytics',
|
|
'db_watch_progress',
|
|
'db_notifications',
|
|
'db_queue_jobs',
|
|
'db_live_streams',
|
|
'db_stream_chat',
|
|
'db_admin_logs',
|
|
'db_user_follows',
|
|
'db_content_categories',
|
|
'db_content_tags',
|
|
'db_content_category_relations'
|
|
];
|
|
|
|
$existingTables = [];
|
|
$missingTables = [];
|
|
|
|
foreach ($newTables as $table) {
|
|
$query = "SHOW TABLES LIKE '{$table}'";
|
|
$result = $this->db->doQuery($query);
|
|
|
|
if ($this->db->doFetch($result)) {
|
|
$existingTables[] = $table;
|
|
} else {
|
|
$missingTables[] = $table;
|
|
}
|
|
}
|
|
|
|
if (empty($missingTables)) {
|
|
return [
|
|
'success' => true,
|
|
'message' => 'All database tables exist'
|
|
];
|
|
} else {
|
|
return [
|
|
'success' => false,
|
|
'message' => count($missingTables) . ' tables missing',
|
|
'details' => array_merge(
|
|
['Run: mysql -u username -p database < __install/easystream.sql'],
|
|
['Missing tables: ' . implode(', ', $missingTables)]
|
|
)
|
|
];
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
return [
|
|
'success' => false,
|
|
'message' => 'Database check failed: ' . $e->getMessage()
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Configure file permissions
|
|
*/
|
|
private function configurePermissions()
|
|
{
|
|
$paths = [
|
|
'f_data' => 0755,
|
|
'logs' => 0755,
|
|
'f_templates' => 0644
|
|
];
|
|
|
|
$configured = 0;
|
|
$errors = [];
|
|
|
|
foreach ($paths as $path => $permission) {
|
|
$fullPath = _FPATH . $path;
|
|
|
|
if (file_exists($fullPath)) {
|
|
if (chmod($fullPath, $permission)) {
|
|
$configured++;
|
|
} else {
|
|
$errors[] = "Failed to set permissions on: {$path}";
|
|
}
|
|
}
|
|
}
|
|
|
|
return [
|
|
'success' => empty($errors),
|
|
'message' => empty($errors) ?
|
|
"Configured permissions for {$configured} paths" :
|
|
'Permission configuration failed',
|
|
'details' => $errors
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Setup cron jobs
|
|
*/
|
|
private function setupCronJobs()
|
|
{
|
|
$cronJobs = [
|
|
'0 2 * * * cd ' . _FPATH . ' && php -f start-workers.php >/dev/null 2>&1',
|
|
'*/5 * * * * cd ' . _FPATH . ' && php -f f_core/f_workers/queue-monitor.php >/dev/null 2>&1'
|
|
];
|
|
|
|
$cronFile = _FPATH . 'easystream-cron.txt';
|
|
|
|
$cronContent = "# EasyStream Cron Jobs\n";
|
|
$cronContent .= "# Add these to your crontab with: crontab easystream-cron.txt\n\n";
|
|
|
|
foreach ($cronJobs as $job) {
|
|
$cronContent .= $job . "\n";
|
|
}
|
|
|
|
if (file_put_contents($cronFile, $cronContent)) {
|
|
return [
|
|
'success' => true,
|
|
'message' => 'Cron jobs file created: easystream-cron.txt',
|
|
'details' => ['Run: crontab easystream-cron.txt']
|
|
];
|
|
} else {
|
|
return [
|
|
'success' => false,
|
|
'message' => 'Failed to create cron jobs file'
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test core components
|
|
*/
|
|
private function testComponents()
|
|
{
|
|
$tests = [
|
|
'Video Processor' => $this->testVideoProcessor(),
|
|
'Queue System' => $this->testQueueSystem(),
|
|
'Social Features' => $this->testSocialFeatures(),
|
|
'Streaming System' => $this->testStreamingSystem(),
|
|
'Live Streaming' => $this->testLiveStreaming(),
|
|
'Admin System' => $this->testAdminSystem(),
|
|
'Content Manager' => $this->testContentManager()
|
|
];
|
|
|
|
$passed = 0;
|
|
$failed = [];
|
|
|
|
foreach ($tests as $component => $result) {
|
|
if ($result) {
|
|
$passed++;
|
|
} else {
|
|
$failed[] = $component;
|
|
}
|
|
}
|
|
|
|
return [
|
|
'success' => empty($failed),
|
|
'message' => empty($failed) ?
|
|
"All {$passed} components working" :
|
|
count($failed) . ' components failed',
|
|
'details' => $failed
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Generate production configuration
|
|
*/
|
|
private function generateConfig()
|
|
{
|
|
$config = [
|
|
'production' => true,
|
|
'debug' => false,
|
|
'log_level' => 'info',
|
|
'queue_workers' => [
|
|
'video_processing' => 2,
|
|
'general' => 1
|
|
],
|
|
'cleanup_schedule' => [
|
|
'logs_retention_days' => 30,
|
|
'temp_files_max_age_hours' => 24,
|
|
'analytics_retention_days' => 90
|
|
],
|
|
'video_processing' => [
|
|
'default_formats' => ['1080p', '720p', '480p', '360p'],
|
|
'generate_hls' => true,
|
|
'generate_thumbnails' => true
|
|
]
|
|
];
|
|
|
|
$configFile = _FPATH . 'production-config.json';
|
|
|
|
if (file_put_contents($configFile, json_encode($config, JSON_PRETTY_PRINT))) {
|
|
return [
|
|
'success' => true,
|
|
'message' => 'Production config created: production-config.json'
|
|
];
|
|
} else {
|
|
return [
|
|
'success' => false,
|
|
'message' => 'Failed to create production config'
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper methods for testing
|
|
*/
|
|
private function checkFFmpeg()
|
|
{
|
|
$output = shell_exec('ffmpeg -version 2>&1');
|
|
return strpos($output, 'ffmpeg version') !== false;
|
|
}
|
|
|
|
private function checkRedis()
|
|
{
|
|
try {
|
|
$redis = VRedis::getInstance();
|
|
return $redis->isConnected();
|
|
} catch (Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function checkDatabase()
|
|
{
|
|
try {
|
|
$query = "SELECT 1";
|
|
$result = $this->db->doQuery($query);
|
|
return $result !== false;
|
|
} catch (Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function testVideoProcessor()
|
|
{
|
|
try {
|
|
$processor = new VVideoProcessor();
|
|
return true;
|
|
} catch (Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function testQueueSystem()
|
|
{
|
|
try {
|
|
$queueManager = new VQueueManager();
|
|
$health = $queueManager->healthCheck();
|
|
return $health['status'] !== 'unhealthy';
|
|
} catch (Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function testSocialFeatures()
|
|
{
|
|
try {
|
|
$social = VSocial::getInstance();
|
|
return true;
|
|
} catch (Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function testStreamingSystem()
|
|
{
|
|
try {
|
|
$streaming = new VStreaming();
|
|
return true;
|
|
} catch (Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function testLiveStreaming()
|
|
{
|
|
try {
|
|
$liveStreaming = new VLiveStreaming();
|
|
return true;
|
|
} catch (Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function testAdminSystem()
|
|
{
|
|
try {
|
|
$admin = VAdmin::getInstance();
|
|
return true;
|
|
} catch (Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function testContentManager()
|
|
{
|
|
try {
|
|
$contentManager = VContentManager::getInstance();
|
|
return true;
|
|
} catch (Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// CLI execution
|
|
if (php_sapi_name() === 'cli') {
|
|
$setup = new ProductionSetup();
|
|
$setup->setup();
|
|
} else {
|
|
echo "This script must be run from command line\n";
|
|
}
|
|
?>
|