mirror of
https://github.com/ceratic/MediaCollectorLibary.git
synced 2026-05-13 23:56:46 +02:00
565 lines
19 KiB
PHP
565 lines
19 KiB
PHP
<?php
|
|
|
|
require_once __DIR__ . '/../vendor/autoload.php';
|
|
|
|
// Load helper functions
|
|
require_once __DIR__ . '/../app/helpers.php';
|
|
|
|
// Start sessions for authentication
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
session_start();
|
|
}
|
|
|
|
// Load environment variables
|
|
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/..');
|
|
$dotenv->load();
|
|
|
|
// Load database configuration
|
|
$dbConfig = require __DIR__ . '/../config/database.php';
|
|
\App\Database\Database::setConfig($dbConfig);
|
|
|
|
// Initialize database
|
|
try {
|
|
$pdo = \App\Database\Database::getInstance();
|
|
} catch (Exception $e) {
|
|
die('Database connection failed: ' . $e->getMessage());
|
|
}
|
|
|
|
use Slim\Factory\AppFactory;
|
|
use Slim\Views\Twig;
|
|
use Slim\Views\TwigMiddleware;
|
|
use DI\Container;
|
|
use Twig\TwigFunction;
|
|
use Twig\TwigFilter;
|
|
use \Twig\Extension\DebugExtension;
|
|
|
|
// Create DI Container
|
|
$container = new Container();
|
|
|
|
// Register PDO instance
|
|
$container->set(PDO::class, function () use ($pdo) {
|
|
return $pdo;
|
|
});
|
|
|
|
// Register Twig view
|
|
$container->set('view', function () use ($container) {
|
|
$twig = Twig::create(__DIR__ . '/../resources/views', [
|
|
'cache' => $_ENV['APP_ENV'] === 'production' ? __DIR__ . '/../storage/views' : false,
|
|
'debug' => $_ENV['APP_DEBUG'] === 'true',
|
|
]);
|
|
$twig->addExtension(new \Twig\Extension\DebugExtension());
|
|
|
|
// Add custom functions
|
|
$twig->getEnvironment()->addFunction(new TwigFunction('base_url', function () {
|
|
return sprintf(
|
|
"%s://%s",
|
|
isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http',
|
|
$_SERVER['HTTP_HOST'] ?? 'localhost'
|
|
);
|
|
}));
|
|
|
|
// Add media visibility function
|
|
$twig->getEnvironment()->addFunction(new TwigFunction('is_media_type_visible', function ($mediaType) {
|
|
return is_media_type_visible($mediaType);
|
|
}));
|
|
|
|
// Placeholder path_for function - will be updated after routes are registered
|
|
$twig->getEnvironment()->addFunction(new TwigFunction('path_for', function ($name, $data = [], $queryParams = []) {
|
|
// Simple implementation for now - will be replaced with proper router-based version
|
|
$basePath = '';
|
|
|
|
// Handle common route patterns
|
|
switch ($name) {
|
|
case 'home':
|
|
$basePath = '/';
|
|
break;
|
|
case 'games.index':
|
|
$basePath = '/media/games';
|
|
break;
|
|
case 'games.show':
|
|
$basePath = '/media/games/' . ($data['game_key'] ?? '');
|
|
break;
|
|
case 'movies.index':
|
|
$basePath = '/media/movies';
|
|
break;
|
|
case 'tvshows.index':
|
|
$basePath = '/media/tv-shows';
|
|
break;
|
|
case 'music.index':
|
|
$basePath = '/media/music';
|
|
break;
|
|
case 'admin.index':
|
|
$basePath = '/admin';
|
|
break;
|
|
case 'admin.playnite.import':
|
|
$basePath = '/admin/playnite/import';
|
|
break;
|
|
case 'admin.playnite.upload':
|
|
$basePath = '/admin/playnite/import';
|
|
break;
|
|
case 'admin.sync':
|
|
$basePath = '/admin/sync/' . ($data['id'] ?? '');
|
|
break;
|
|
case 'auth.login':
|
|
$basePath = '/login';
|
|
break;
|
|
case 'auth.logout':
|
|
$basePath = '/logout';
|
|
break;
|
|
case 'movies.show':
|
|
$basePath = '/media/movies/' . ($data['id'] ?? '');
|
|
break;
|
|
case 'tvshows.show':
|
|
$basePath = '/media/tv-shows/' . ($data['id'] ?? '');
|
|
break;
|
|
case 'music.show':
|
|
$basePath = '/media/music/' . ($data['id'] ?? '');
|
|
break;
|
|
case 'adult.index':
|
|
$basePath = '/media/adult';
|
|
break;
|
|
case 'adult.show':
|
|
$basePath = '/media/adult/' . ($data['id'] ?? '');
|
|
break;
|
|
case 'actors.index':
|
|
$basePath = '/media/actors';
|
|
break;
|
|
case 'actors.show':
|
|
$basePath = '/media/actors/' . ($data['id'] ?? '');
|
|
break;
|
|
case 'actors.edit':
|
|
$basePath = '/media/actors/' . ($data['id'] ?? '') .'/edit';
|
|
break;
|
|
case 'search.index':
|
|
$basePath = '/search';
|
|
break;
|
|
default:
|
|
$basePath = '/' . str_replace('.', '/', $name);
|
|
}
|
|
|
|
// Add query parameters
|
|
if (!empty($queryParams)) {
|
|
$basePath .= '?' . http_build_query($queryParams);
|
|
}
|
|
|
|
return $basePath;
|
|
}));
|
|
|
|
$twig->getEnvironment()->addFunction(new TwigFunction('is_admin', function () use ($container) {
|
|
$authService = $container->get(\App\Services\AuthService::class);
|
|
return $authService->isAdmin();
|
|
}));
|
|
|
|
$twig->getEnvironment()->addFunction(new TwigFunction('current_user', function () use ($container) {
|
|
$authService = $container->get(\App\Services\AuthService::class);
|
|
$user = $authService->getCurrentUser();
|
|
return $user ?: (object)['username' => 'Guest'];
|
|
}));
|
|
|
|
$twig->getEnvironment()->addFunction(new TwigFunction('csrf_token', function () use ($container) {
|
|
$authService = $container->get(\App\Services\AuthService::class);
|
|
return $authService->generateCSRFToken();
|
|
}));
|
|
|
|
$twig->getEnvironment()->addFunction(new TwigFunction('country_flag', function ($countryName) {
|
|
if (!$countryName) {
|
|
return '';
|
|
}
|
|
|
|
// Country name to ISO 3166-1 alpha-2 code mapping (most common countries)
|
|
$countryMap = [
|
|
'United States' => 'us',
|
|
'USA' => 'us',
|
|
'America' => 'us',
|
|
'United Kingdom' => 'gb',
|
|
'UK' => 'gb',
|
|
'Britain' => 'gb',
|
|
'England' => 'gb',
|
|
'Germany' => 'de',
|
|
'France' => 'fr',
|
|
'Italy' => 'it',
|
|
'Spain' => 'es',
|
|
'Canada' => 'ca',
|
|
'Australia' => 'au',
|
|
'Japan' => 'jp',
|
|
'China' => 'cn',
|
|
'India' => 'in',
|
|
'Brazil' => 'br',
|
|
'Mexico' => 'mx',
|
|
'Russia' => 'ru',
|
|
'South Korea' => 'kr',
|
|
'Netherlands' => 'nl',
|
|
'Sweden' => 'se',
|
|
'Norway' => 'no',
|
|
'Denmark' => 'dk',
|
|
'Finland' => 'fi',
|
|
'Poland' => 'pl',
|
|
'Czech Republic' => 'cz',
|
|
'Hungary' => 'hu',
|
|
'Romania' => 'ro',
|
|
'Bulgaria' => 'bg',
|
|
'Greece' => 'gr',
|
|
'Portugal' => 'pt',
|
|
'Belgium' => 'be',
|
|
'Austria' => 'at',
|
|
'Switzerland' => 'ch',
|
|
'Ireland' => 'ie',
|
|
'New Zealand' => 'nz',
|
|
'South Africa' => 'za',
|
|
'Argentina' => 'ar',
|
|
'Chile' => 'cl',
|
|
'Colombia' => 'co',
|
|
'Peru' => 'pe',
|
|
'Venezuela' => 've',
|
|
'Ecuador' => 'ec',
|
|
'Uruguay' => 'uy',
|
|
'Paraguay' => 'py',
|
|
'Bolivia' => 'bo',
|
|
'Thailand' => 'th',
|
|
'Vietnam' => 'vn',
|
|
'Philippines' => 'ph',
|
|
'Indonesia' => 'id',
|
|
'Malaysia' => 'my',
|
|
'Singapore' => 'sg',
|
|
'Turkey' => 'tr',
|
|
'Israel' => 'il',
|
|
'Egypt' => 'eg',
|
|
'Morocco' => 'ma',
|
|
'Tunisia' => 'tn',
|
|
'Algeria' => 'dz',
|
|
'Saudi Arabia' => 'sa',
|
|
'UAE' => 'ae',
|
|
'United Arab Emirates' => 'ae',
|
|
'Qatar' => 'qa',
|
|
'Kuwait' => 'kw',
|
|
'Bahrain' => 'bh',
|
|
'Oman' => 'om',
|
|
'Jordan' => 'jo',
|
|
'Lebanon' => 'lb',
|
|
'Syria' => 'sy',
|
|
'Iraq' => 'iq',
|
|
'Iran' => 'ir',
|
|
'Pakistan' => 'pk',
|
|
'Bangladesh' => 'bd',
|
|
'Sri Lanka' => 'lk',
|
|
'Nepal' => 'np',
|
|
'Bhutan' => 'bt',
|
|
'Maldives' => 'mv',
|
|
'Afghanistan' => 'af',
|
|
'Kazakhstan' => 'kz',
|
|
'Uzbekistan' => 'uz',
|
|
'Turkmenistan' => 'tm',
|
|
'Kyrgyzstan' => 'kg',
|
|
'Tajikistan' => 'tj',
|
|
'Mongolia' => 'mn',
|
|
'North Korea' => 'kp',
|
|
'Taiwan' => 'tw',
|
|
'Hong Kong' => 'hk',
|
|
'Macau' => 'mo',
|
|
'South Korea' => 'kr',
|
|
'Cambodia' => 'kh',
|
|
'Laos' => 'la',
|
|
'Myanmar' => 'mm',
|
|
'Brunei' => 'bn',
|
|
'East Timor' => 'tl',
|
|
'Papua New Guinea' => 'pg',
|
|
'Fiji' => 'fj',
|
|
'Solomon Islands' => 'sb',
|
|
'Vanuatu' => 'vu',
|
|
'Samoa' => 'ws',
|
|
'Tonga' => 'to',
|
|
'Tuvalu' => 'tv',
|
|
'Kiribati' => 'ki',
|
|
'Marshall Islands' => 'mh',
|
|
'Micronesia' => 'fm',
|
|
'Palau' => 'pw',
|
|
'Nauru' => 'nr',
|
|
'Cuba' => 'cu',
|
|
'Jamaica' => 'jm',
|
|
'Haiti' => 'ht',
|
|
'Dominican Republic' => 'do',
|
|
'Puerto Rico' => 'pr',
|
|
'Bahamas' => 'bs',
|
|
'Trinidad and Tobago' => 'tt',
|
|
'Barbados' => 'bb',
|
|
'Saint Lucia' => 'lc',
|
|
'Saint Vincent and the Grenadines' => 'vc',
|
|
'Grenada' => 'gd',
|
|
'Antigua and Barbuda' => 'ag',
|
|
'Saint Kitts and Nevis' => 'kn',
|
|
'Dominica' => 'dm',
|
|
'Saint Martin' => 'mf',
|
|
'Guadeloupe' => 'gp',
|
|
'Martinique' => 'mq',
|
|
'French Guiana' => 'gf',
|
|
'Suriname' => 'sr',
|
|
'Guyana' => 'gy',
|
|
'Belize' => 'bz',
|
|
'Costa Rica' => 'cr',
|
|
'Panama' => 'pa',
|
|
'Nicaragua' => 'ni',
|
|
'Honduras' => 'hn',
|
|
'El Salvador' => 'sv',
|
|
'Guatemala' => 'gt',
|
|
'Greenland' => 'gl',
|
|
'Iceland' => 'is',
|
|
'Faroe Islands' => 'fo',
|
|
'Åland Islands' => 'ax',
|
|
'Guernsey' => 'gg',
|
|
'Jersey' => 'je',
|
|
'Isle of Man' => 'im',
|
|
'Gibraltar' => 'gi',
|
|
'Malta' => 'mt',
|
|
'Cyprus' => 'cy',
|
|
'Luxembourg' => 'lu',
|
|
'Monaco' => 'mc',
|
|
'Andorra' => 'ad',
|
|
'San Marino' => 'sm',
|
|
'Vatican City' => 'va',
|
|
'Liechtenstein' => 'li',
|
|
'Slovenia' => 'si',
|
|
'Croatia' => 'hr',
|
|
'Bosnia and Herzegovina' => 'ba',
|
|
'Serbia' => 'rs',
|
|
'Montenegro' => 'me',
|
|
'Kosovo' => 'xk',
|
|
'North Macedonia' => 'mk',
|
|
'Albania' => 'al',
|
|
'Moldova' => 'md',
|
|
'Ukraine' => 'ua',
|
|
'Belarus' => 'by',
|
|
'Lithuania' => 'lt',
|
|
'Latvia' => 'lv',
|
|
'Estonia' => 'ee',
|
|
'Slovakia' => 'sk',
|
|
'Armenia' => 'am',
|
|
'Azerbaijan' => 'az',
|
|
'Georgia' => 'ge',
|
|
];
|
|
|
|
$countryCode = strtolower($countryMap[$countryName] ?? '');
|
|
|
|
if ($countryCode) {
|
|
// Return Iconify flag icon HTML
|
|
return '<span class="iconify" data-icon="flag:' . $countryCode . '-4x3" data-inline="false" style="width: 20px; height: 15px; display: inline-block;"></span>';
|
|
}
|
|
|
|
return '';
|
|
}));
|
|
|
|
$twig->getEnvironment()->addFilter(new TwigFilter('format_duration', function ($minutes) {
|
|
if (!$minutes || $minutes == 0) {
|
|
return '0m';
|
|
}
|
|
|
|
$hours = floor($minutes / 60);
|
|
$remainingMinutes = $minutes % 60;
|
|
|
|
if ($hours > 0) {
|
|
return $hours . 'h ' . $remainingMinutes . 'm';
|
|
}
|
|
|
|
return $remainingMinutes . 'm';
|
|
}));
|
|
|
|
$twig->getEnvironment()->addFilter(new TwigFilter('json_decode', function ($jsonString) {
|
|
if (!$jsonString) {
|
|
return null;
|
|
}
|
|
|
|
$decoded = json_decode($jsonString, true);
|
|
return $decoded === null ? null : $decoded;
|
|
}));
|
|
|
|
$twig->getEnvironment()->addFilter(new TwigFilter('filesizeformat', function ($bytes) {
|
|
if (!$bytes || !is_numeric($bytes)) {
|
|
return '0 B';
|
|
}
|
|
|
|
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
$bytes = max($bytes, 0);
|
|
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
|
$pow = min($pow, count($units) - 1);
|
|
|
|
$bytes /= pow(1024, $pow);
|
|
|
|
return round($bytes, 2) . ' ' . $units[$pow];
|
|
}));
|
|
|
|
return $twig;
|
|
});
|
|
|
|
// Register AuthService
|
|
$container->set(\App\Services\AuthService::class, function ($c) {
|
|
return new \App\Services\AuthService($c->get(PDO::class));
|
|
});
|
|
|
|
// Register models
|
|
$container->set(\App\Models\User::class, function ($c) {
|
|
return new \App\Models\User($c->get(PDO::class));
|
|
});
|
|
|
|
$container->set(\App\Models\SyncLog::class, function ($c) {
|
|
return new \App\Models\SyncLog($c->get(PDO::class));
|
|
});
|
|
|
|
// Register controllers
|
|
$container->set(\App\Controllers\AuthController::class, function ($c) {
|
|
return new \App\Controllers\AuthController($c->get(\App\Services\AuthService::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\AdminController::class, function ($c) {
|
|
return new \App\Controllers\AdminController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\GameController::class, function ($c) {
|
|
return new \App\Controllers\GameController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\DashboardController::class, function ($c) {
|
|
return new \App\Controllers\DashboardController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\MovieController::class, function ($c) {
|
|
return new \App\Controllers\MovieController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\TvShowController::class, function ($c) {
|
|
return new \App\Controllers\TvShowController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\MusicController::class, function ($c) {
|
|
return new \App\Controllers\MusicController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\AdultController::class, function ($c) {
|
|
return new \App\Controllers\AdultController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\ActorController::class, function ($c) {
|
|
return new \App\Controllers\ActorController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\SearchController::class, function ($c) {
|
|
return new \App\Controllers\SearchController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\ImageController::class, function ($c) {
|
|
return new \App\Controllers\ImageController($c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Controllers\SettingsController::class, function ($c) {
|
|
return new \App\Controllers\SettingsController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
// Register API controllers
|
|
$container->set(\App\Controllers\Api\PlayniteController::class, function ($c) {
|
|
return new \App\Controllers\Api\PlayniteController($c->get(PDO::class));
|
|
});
|
|
|
|
$container->set(\App\Controllers\Api\AuthController::class, function ($c) {
|
|
return new \App\Controllers\Api\AuthController($c->get(\App\Services\AuthService::class));
|
|
});
|
|
|
|
// Register PlayniteImportService
|
|
$container->set(\App\Services\PlayniteImportService::class, function ($c) {
|
|
return new \App\Services\PlayniteImportService($c->get(PDO::class));
|
|
});
|
|
|
|
// Register middleware
|
|
$container->set(\App\Http\Middleware\AuthMiddleware::class, function ($c) {
|
|
return new \App\Http\Middleware\AuthMiddleware($c->get(\App\Services\AuthService::class));
|
|
});
|
|
|
|
$container->set(\App\Controllers\MediaSourceController::class, function ($c) {
|
|
return new \App\Controllers\MediaSourceController($c->get(PDO::class), $c->get('view'));
|
|
});
|
|
|
|
$container->set(\App\Http\Middleware\MediaVisibilityMiddleware::class, function ($c) {
|
|
return new \App\Http\Middleware\MediaVisibilityMiddleware();
|
|
});
|
|
|
|
// Create App with DI Container
|
|
AppFactory::setContainer($container);
|
|
$app = AppFactory::create();
|
|
|
|
// Add Twig-View Middleware
|
|
$twig = $container->get('view');
|
|
$app->add(TwigMiddleware::create($app, $twig));
|
|
|
|
// PHP DebugBar Setup (only in development)
|
|
if ($_ENV['APP_DEBUG'] === 'true') {
|
|
$debugbar = new \DebugBar\StandardDebugBar();
|
|
|
|
// Set up the debug bar renderer with the correct base URL
|
|
$baseUrl = rtrim($app->getBasePath(), '/');
|
|
$debugbarRenderer = $debugbar->getJavascriptRenderer($baseUrl . '/phpdebugbar');
|
|
|
|
// Add DebugBar to Twig globals
|
|
$twig->getEnvironment()->addGlobal('debugbarRenderer', $debugbarRenderer);
|
|
|
|
// Add route to serve DebugBar assets
|
|
$app->get('/phpdebugbar/{path:.*}', function ($request, $response, $args) use ($debugbar) {
|
|
$debugbarRenderer = $debugbar->getJavascriptRenderer();
|
|
$path = $args['path'];
|
|
|
|
// Serve CSS files
|
|
if (preg_match('/\.css$/', $path)) {
|
|
$content = file_get_contents($debugbarRenderer->getBasePath() . '/' . $path);
|
|
$response->getBody()->write($content);
|
|
return $response->withHeader('Content-Type', 'text/css');
|
|
}
|
|
|
|
// Serve JS files
|
|
if (preg_match('/\.js$/', $path)) {
|
|
$content = file_get_contents($debugbarRenderer->getBasePath() . '/' . $path);
|
|
$response->getBody()->write($content);
|
|
return $response->withHeader('Content-Type', 'application/javascript');
|
|
}
|
|
|
|
// Serve other assets (fonts, etc.)
|
|
$content = @file_get_contents($debugbarRenderer->getBasePath() . '/' . $path);
|
|
if ($content !== false) {
|
|
$response->getBody()->write($content);
|
|
return $response;
|
|
}
|
|
|
|
return $response->withStatus(404);
|
|
});
|
|
|
|
// Add middleware to collect data
|
|
$app->add(function ($request, $handler) use ($debugbar) {
|
|
// Start timing the request
|
|
$debugbar['time']->startMeasure('app', 'Application');
|
|
|
|
try {
|
|
$response = $handler->handle($request);
|
|
|
|
// Stop timing if it was started
|
|
if ($debugbar['time']->hasStartedMeasure('app')) {
|
|
$debugbar['time']->stopMeasure('app');
|
|
}
|
|
|
|
return $response;
|
|
} catch (\Exception $e) {
|
|
// Make sure to stop timing even if an exception occurs
|
|
if ($debugbar['time']->hasStartedMeasure('app')) {
|
|
$debugbar['time']->stopMeasure('app');
|
|
}
|
|
throw $e;
|
|
}
|
|
});
|
|
}
|
|
// Add Error Middleware
|
|
$errorMiddleware = $app->addErrorMiddleware(
|
|
$_ENV['APP_DEBUG'] === 'true',
|
|
true,
|
|
true
|
|
);
|
|
|
|
// Register routes
|
|
require __DIR__ . '/../routes/web.php';
|
|
require __DIR__ . '/../routes/api.php';
|
|
|
|
$app->run();
|