322 lines
9.8 KiB
PHP
322 lines
9.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require __DIR__ . '/Support/functions.php';
|
|
require __DIR__ . '/Repository/RecordRepositoryInterface.php';
|
|
require __DIR__ . '/Repository/JsonRepository.php';
|
|
require __DIR__ . '/Repository/MySqlJsonRepository.php';
|
|
require __DIR__ . '/Services/BookingService.php';
|
|
require __DIR__ . '/Services/InvoicePdfService.php';
|
|
|
|
session_start();
|
|
|
|
function runApplication(): void
|
|
{
|
|
$config = require dirname(__DIR__) . '/config.php';
|
|
setAppConfig($config);
|
|
|
|
[$bookingRepository, $invoiceRepository] = resolveRepositories($config);
|
|
|
|
$bookingService = new BookingService($bookingRepository, $invoiceRepository, $config);
|
|
$invoicePdfService = new InvoicePdfService($config);
|
|
|
|
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
|
|
$path = requestPath();
|
|
|
|
if (serveStaticAssetIfRequested($path)) {
|
|
return;
|
|
}
|
|
|
|
if ($method === 'POST' && $path === '/book') {
|
|
handlePublicBooking($bookingService);
|
|
return;
|
|
}
|
|
|
|
if ($method === 'POST' && $path === '/admin/login') {
|
|
handleAdminLogin($config['admin']);
|
|
return;
|
|
}
|
|
|
|
if ($method === 'POST' && $path === '/admin/logout') {
|
|
handleAdminLogout();
|
|
return;
|
|
}
|
|
|
|
if ($path === '/admin/invoice/pdf') {
|
|
requireAdmin();
|
|
handleInvoicePdf($bookingService, $invoicePdfService);
|
|
return;
|
|
}
|
|
|
|
if (str_starts_with($path, '/admin')) {
|
|
handleAdminRequest($path, $method, $bookingService);
|
|
return;
|
|
}
|
|
|
|
renderHome($bookingService, $config);
|
|
}
|
|
|
|
function requestPath(): string
|
|
{
|
|
$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/';
|
|
$basePath = basePath();
|
|
|
|
if ($basePath !== '' && str_starts_with($path, $basePath)) {
|
|
$path = substr($path, strlen($basePath)) ?: '/';
|
|
}
|
|
|
|
if ($path === '') {
|
|
return '/';
|
|
}
|
|
|
|
return '/' . ltrim($path, '/');
|
|
}
|
|
|
|
function serveStaticAssetIfRequested(string $path): bool
|
|
{
|
|
if (!str_starts_with($path, '/assets/')) {
|
|
return false;
|
|
}
|
|
|
|
$file = dirname(__DIR__) . $path;
|
|
if (!is_file($file)) {
|
|
http_response_code(404);
|
|
echo 'Datei nicht gefunden.';
|
|
return true;
|
|
}
|
|
|
|
$extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
|
$mimeTypes = [
|
|
'css' => 'text/css; charset=UTF-8',
|
|
'js' => 'application/javascript; charset=UTF-8',
|
|
'svg' => 'image/svg+xml',
|
|
'png' => 'image/png',
|
|
'jpg' => 'image/jpeg',
|
|
'jpeg' => 'image/jpeg',
|
|
'webp' => 'image/webp',
|
|
];
|
|
|
|
header('Content-Type: ' . ($mimeTypes[$extension] ?? 'application/octet-stream'));
|
|
header('Content-Length: ' . (string) filesize($file));
|
|
readfile($file);
|
|
|
|
return true;
|
|
}
|
|
|
|
function resolveRepositories(array $config): array
|
|
{
|
|
$databaseFile = $config['database']['credentials_file'];
|
|
if (file_exists($databaseFile)) {
|
|
$databaseConfig = require $databaseFile;
|
|
if (is_array($databaseConfig) && ($databaseConfig['enabled'] ?? false) === true) {
|
|
try {
|
|
$tablePrefix = (string) ($databaseConfig['table_prefix'] ?? $config['database']['table_prefix'] ?? '');
|
|
$dsn = sprintf(
|
|
'mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4',
|
|
$databaseConfig['host'],
|
|
$databaseConfig['port'] ?? 3306,
|
|
$databaseConfig['database']
|
|
);
|
|
|
|
$pdo = new PDO($dsn, $databaseConfig['username'], $databaseConfig['password'], [
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
]);
|
|
|
|
return [
|
|
new MySqlJsonRepository($pdo, resolveTableName($tablePrefix, $config['database']['tables']['bookings'])),
|
|
new MySqlJsonRepository($pdo, resolveTableName($tablePrefix, $config['database']['tables']['invoices'])),
|
|
];
|
|
} catch (Throwable $exception) {
|
|
error_log('MySQL-Verbindung fehlgeschlagen, JSON-Fallback aktiv: ' . $exception->getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
return [
|
|
new JsonRepository($config['storage']['bookings']),
|
|
new JsonRepository($config['storage']['invoices']),
|
|
];
|
|
}
|
|
|
|
function resolveTableName(string $prefix, string $table): string
|
|
{
|
|
return $prefix . $table;
|
|
}
|
|
|
|
function handlePublicBooking(BookingService $bookingService): void
|
|
{
|
|
try {
|
|
$bookingService->createPublicBooking($_POST);
|
|
flash('success', 'Deine Anfrage wurde gespeichert. Wir melden uns zeitnah mit der Bestaetigung und allen Details.');
|
|
} catch (Throwable $exception) {
|
|
flash('error', $exception->getMessage());
|
|
flash('old', $_POST);
|
|
}
|
|
|
|
redirect('/');
|
|
}
|
|
|
|
function handleAdminLogin(array $adminConfig): void
|
|
{
|
|
$username = trim((string) ($_POST['username'] ?? ''));
|
|
$password = (string) ($_POST['password'] ?? '');
|
|
|
|
if ($username === $adminConfig['username'] && hash_equals($adminConfig['password'], $password)) {
|
|
$_SESSION['admin_authenticated'] = true;
|
|
flash('success', 'Admin-Bereich geoeffnet.');
|
|
} else {
|
|
flash('error', 'Die Admin-Zugangsdaten sind nicht korrekt.');
|
|
}
|
|
|
|
redirect('/admin');
|
|
}
|
|
|
|
function handleAdminLogout(): void
|
|
{
|
|
unset($_SESSION['admin_authenticated']);
|
|
flash('success', 'Du wurdest aus dem Admin-Bereich abgemeldet.');
|
|
redirect('/admin');
|
|
}
|
|
|
|
function handleAdminRequest(string $path, string $method, BookingService $bookingService): void
|
|
{
|
|
if (!isAdminAuthenticated()) {
|
|
renderAdminLogin();
|
|
return;
|
|
}
|
|
|
|
if ($method === 'POST' && $path === '/admin/create') {
|
|
try {
|
|
$bookingService->createAdminBooking($_POST);
|
|
flash('success', 'Die Bestellung wurde fuer den Kunden angelegt.');
|
|
} catch (Throwable $exception) {
|
|
flash('error', $exception->getMessage());
|
|
flash('admin_old', $_POST);
|
|
}
|
|
|
|
redirect('/admin/create');
|
|
}
|
|
|
|
if ($method === 'POST' && $path === '/admin/order/update') {
|
|
try {
|
|
$bookingService->updateBooking((string) ($_POST['booking_id'] ?? ''), $_POST);
|
|
flash('success', 'Der Auftrag wurde aktualisiert.');
|
|
} catch (Throwable $exception) {
|
|
flash('error', $exception->getMessage());
|
|
}
|
|
|
|
redirect('admin/order?id=' . urlencode((string) ($_POST['booking_id'] ?? '')));
|
|
}
|
|
|
|
if ($method === 'POST' && $path === '/admin/order/invoice') {
|
|
try {
|
|
$invoiceId = $bookingService->createInvoiceForBooking((string) ($_POST['booking_id'] ?? ''), $_POST);
|
|
flash('success', 'Die Rechnung wurde erstellt.');
|
|
redirect('admin/order?id=' . urlencode((string) ($_POST['booking_id'] ?? '')) . '&invoice=' . urlencode($invoiceId));
|
|
} catch (Throwable $exception) {
|
|
flash('error', $exception->getMessage());
|
|
redirect('admin/order?id=' . urlencode((string) ($_POST['booking_id'] ?? '')));
|
|
}
|
|
}
|
|
|
|
if ($path === '/admin/create') {
|
|
renderAdminCreate($bookingService);
|
|
return;
|
|
}
|
|
|
|
if ($path === '/admin/order') {
|
|
renderAdminOrder($bookingService);
|
|
return;
|
|
}
|
|
|
|
renderAdminDashboard($bookingService);
|
|
}
|
|
|
|
function handleInvoicePdf(BookingService $bookingService, InvoicePdfService $invoicePdfService): void
|
|
{
|
|
$invoiceId = (string) ($_GET['id'] ?? '');
|
|
$invoice = $bookingService->findInvoice($invoiceId);
|
|
|
|
if ($invoice === null) {
|
|
http_response_code(404);
|
|
echo 'Rechnung nicht gefunden.';
|
|
return;
|
|
}
|
|
|
|
$pdf = $invoicePdfService->render($invoice);
|
|
|
|
header('Content-Type: application/pdf');
|
|
header('Content-Disposition: inline; filename="' . $invoice['invoice_number'] . '.pdf"');
|
|
header('Content-Length: ' . strlen($pdf));
|
|
|
|
echo $pdf;
|
|
}
|
|
|
|
function renderHome(BookingService $bookingService, array $config): void
|
|
{
|
|
render('home', [
|
|
'pageTitle' => 'Fotobox mieten',
|
|
'config' => $config,
|
|
'flashSuccess' => flash('success'),
|
|
'flashError' => flash('error'),
|
|
'old' => flash('old') ?? [],
|
|
'bookings' => $bookingService->getHighlightedBookings(),
|
|
]);
|
|
}
|
|
|
|
function renderAdminLogin(): void
|
|
{
|
|
render('admin/login', [
|
|
'pageTitle' => 'Admin Login',
|
|
'flashSuccess' => flash('success'),
|
|
'flashError' => flash('error'),
|
|
]);
|
|
}
|
|
|
|
function renderAdminDashboard(BookingService $bookingService): void
|
|
{
|
|
render('admin/dashboard', [
|
|
'pageTitle' => 'Admin Dashboard',
|
|
'flashSuccess' => flash('success'),
|
|
'flashError' => flash('error'),
|
|
'stats' => $bookingService->getDashboardStats(),
|
|
'bookings' => $bookingService->getBookings(),
|
|
'invoices' => $bookingService->getInvoices(),
|
|
]);
|
|
}
|
|
|
|
function renderAdminCreate(BookingService $bookingService): void
|
|
{
|
|
render('admin/create', [
|
|
'pageTitle' => 'Kundenbestellung anlegen',
|
|
'flashSuccess' => flash('success'),
|
|
'flashError' => flash('error'),
|
|
'old' => flash('admin_old') ?? [],
|
|
'defaults' => $bookingService->getAdminDefaults(),
|
|
]);
|
|
}
|
|
|
|
function renderAdminOrder(BookingService $bookingService): void
|
|
{
|
|
$bookingId = (string) ($_GET['id'] ?? '');
|
|
$booking = $bookingService->findBooking($bookingId);
|
|
|
|
if ($booking === null) {
|
|
http_response_code(404);
|
|
echo 'Auftrag nicht gefunden.';
|
|
return;
|
|
}
|
|
|
|
render('admin/order', [
|
|
'pageTitle' => 'Auftrag ' . $booking['reference'],
|
|
'flashSuccess' => flash('success'),
|
|
'flashError' => flash('error'),
|
|
'booking' => $booking,
|
|
'invoice' => $booking['invoice_id'] ? $bookingService->findInvoice($booking['invoice_id']) : null,
|
|
'statusOptions' => $bookingService->getStatusOptions(),
|
|
'paymentOptions' => $bookingService->getPaymentStatusOptions(),
|
|
]);
|
|
}
|