88 lines
2.7 KiB
PHP
88 lines
2.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Core;
|
|
|
|
use Dotenv\Dotenv;
|
|
use App\Core\{Request, Response, Router, Container};
|
|
|
|
final class Application
|
|
{
|
|
private Container $container;
|
|
private Router $router;
|
|
public static ?array $config = null;
|
|
|
|
public function __construct(string $basePath)
|
|
{
|
|
// 1. Load Environment Variables
|
|
// In local dev, .env is in the project root. In production, it might be moved.
|
|
$dotenv = Dotenv::createImmutable($basePath);
|
|
$dotenv->load();
|
|
|
|
// 2. Set Timezone
|
|
date_default_timezone_set($_ENV['APP_TIMEZONE'] ?? 'Asia/Amman');
|
|
|
|
// 3. Initialize Core Components
|
|
$this->container = new Container();
|
|
|
|
// 4. Load Configurations
|
|
$this->loadConfigs($basePath);
|
|
|
|
$this->router = new Router($this->container);
|
|
|
|
// Register core services in container
|
|
$this->container->set(Container::class, $this->container);
|
|
$this->container->set(Router::class, $this->router);
|
|
}
|
|
|
|
private function loadConfigs(string $basePath): void
|
|
{
|
|
$configPath = $basePath . '/config';
|
|
$configs = [];
|
|
|
|
foreach (glob($configPath . '/*.php') as $file) {
|
|
$key = basename($file, '.php');
|
|
$configs[$key] = require $file;
|
|
}
|
|
|
|
self::$config = $configs;
|
|
$this->container->set('config', $configs);
|
|
}
|
|
|
|
public function getRouter(): Router
|
|
{
|
|
return $this->router;
|
|
}
|
|
|
|
public function run(): void
|
|
{
|
|
// 1. Security Headers
|
|
header('X-Content-Type-Options: nosniff');
|
|
header('X-Frame-Options: DENY');
|
|
header('X-XSS-Protection: 1; mode=block');
|
|
header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
|
|
header('Referrer-Policy: strict-origin-when-cross-origin');
|
|
header('Permissions-Policy: camera=(), microphone=(), geolocation=()');
|
|
header('Content-Security-Policy: default-src \'self\'; script-src \'self\' cdn.tailwindcss.com unpkg.com; style-src \'self\' \'unsafe-inline\' fonts.googleapis.com; font-src fonts.gstatic.com');
|
|
header_remove('X-Powered-By');
|
|
|
|
try {
|
|
$request = new Request();
|
|
$this->router->dispatch($request, $this->container);
|
|
} catch (\Throwable $e) {
|
|
// Global Exception Handler
|
|
Response::error(
|
|
'حدث خطأ غير متوقع في النظام',
|
|
'INTERNAL_SERVER_ERROR',
|
|
500,
|
|
[
|
|
'message' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine()
|
|
]
|
|
);
|
|
}
|
|
}
|
|
}
|