| Server IP : 193.86.120.172 / Your IP : 216.73.216.215 Web Server : Apache/2.4.63 (Unix) System : Linux JServices 3.10.108 #86003 SMP Wed Oct 22 13:20:46 CST 2025 x86_64 User : kubec ( 1026) PHP Version : 8.2.28 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /volume1/web/kadernictvi_jservices_cz/includes/ |
Upload File : |
<?php
// ============================================
// includes/db.php
// PDO připojení + pomocné funkce
// ============================================
require_once __DIR__ . '/config.php';
function db(): PDO {
static $pdo = null;
if ($pdo === null) {
$dsn = sprintf('mysql:host=%s;dbname=%s;charset=%s', DB_HOST, DB_NAME, DB_CHARSET);
$pdo = new PDO($dsn, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => true,
]);
}
return $pdo;
}
// -----------------------------------------------
// Nastavení salónu z DB (cache na request)
// -----------------------------------------------
function nastaveni(string $klic, mixed $vychozi = null): mixed {
static $cache = null;
if ($cache === null) {
$cache = [];
try {
$rows = db()->query("SELECT klic, hodnota FROM nastaveni")->fetchAll();
foreach ($rows as $r) {
$cache[$r['klic']] = $r['hodnota'];
}
} catch (Exception $e) {
// Tabulka ještě neexistuje při první instalaci – vrátí výchozí hodnoty
}
}
return $cache[$klic] ?? $vychozi;
}
function slot_minut(): int { return (int) nastaveni('slot_minut', 30); }
function salon_nazev(): string { return (string) nastaveni('salon_nazev', 'Kadeřnictví Stella'); }
// Načte pracovní dobu pro konkrétní den (1=Po…7=Ne), nebo null pokud zavřeno
function pracovni_doba_dne(int $dow): ?array {
static $cache = [];
if (!isset($cache[$dow])) {
try {
$stmt = db()->prepare("SELECT od_min, do_min FROM pracovni_doba WHERE den = ? AND aktivni = 1");
$stmt->execute([$dow]);
$row = $stmt->fetch();
$cache[$dow] = $row ?: null;
} catch (Exception $e) {
// Tabulka ještě neexistuje — fallback na nastaveni
$od = (int) nastaveni('pracovni_od', 480);
$do = (int) nastaveni('pracovni_do', 1020);
$dny = array_map('intval', explode(',', nastaveni('pracovni_dny', '1,2,3,4,5,6')));
$cache[$dow] = in_array($dow, $dny) ? ['od_min' => $od, 'do_min' => $do] : null;
}
}
return $cache[$dow];
}
// Vrátí všechny aktivní pracovní dny s jejich dobou
function vsechna_pracovni_doba(): array {
static $cache = null;
if ($cache === null) {
try {
$stmt = db()->query("SELECT den, od_min, do_min FROM pracovni_doba WHERE aktivni = 1 ORDER BY den");
$cache = $stmt->fetchAll(PDO::FETCH_KEY_PAIR | PDO::FETCH_UNIQUE) ?: [];
// Přegeneruj jako den => [od_min, do_min]
$stmt2 = db()->query("SELECT den, od_min, do_min FROM pracovni_doba WHERE aktivni = 1 ORDER BY den");
$cache = [];
foreach ($stmt2->fetchAll() as $r) {
$cache[$r['den']] = ['od_min' => (int)$r['od_min'], 'do_min' => (int)$r['do_min']];
}
} catch (Exception $e) {
$cache = [];
}
}
return $cache;
}
// -----------------------------------------------
// Pomocné funkce
// -----------------------------------------------
function json_response(array $data, int $status = 200): void {
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
header('X-Content-Type-Options: nosniff');
echo json_encode($data, JSON_UNESCAPED_UNICODE);
exit;
}
function json_error(string $message, int $status = 400): void {
json_response(['ok' => false, 'error' => $message], $status);
}
function generate_token(): string {
return bin2hex(random_bytes(32));
}
function sanitize(string $value): string {
return trim($value);
}
function valid_email(string $email): bool {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
function valid_date(string $date): bool {
$d = DateTime::createFromFormat('Y-m-d', $date);
return $d && $d->format('Y-m-d') === $date;
}
// -----------------------------------------------
// Logika volných termínů
// -----------------------------------------------
function obsazene_sloty(string $datum): array {
$stmt = db()->prepare("
SELECT cas_od, cas_do FROM rezervace
WHERE datum = ? AND stav != 'zrusena'
");
$stmt->execute([$datum]);
$obsazene = [];
foreach ($stmt->fetchAll() as $r) {
$od = strtotime($r['cas_od']);
$do = strtotime($r['cas_do']);
for ($t = $od; $t < $do; $t += slot_minut() * 60) {
$obsazene[] = date('H:i', $t);
}
}
return array_unique($obsazene);
}
function volne_casy(string $datum, int $trvani_min): array {
if (je_blokovany_den($datum)) return [];
$dow = (int) date('N', strtotime($datum)); // 1=Po, 7=Ne
$doba = pracovni_doba_dne($dow);
if (!$doba) return []; // Tento den je zavřeno
$y = (int) substr($datum, 0, 4);
$m = (int) substr($datum, 5, 2);
$d = (int) substr($datum, 8, 2);
$denni_od = mktime(intdiv($doba['od_min'], 60), $doba['od_min'] % 60, 0, $m, $d, $y);
$denni_do = mktime(intdiv($doba['do_min'], 60), $doba['do_min'] % 60, 0, $m, $d, $y);
$obsazene = obsazene_sloty($datum);
$slot = slot_minut() * 60;
$volne = [];
for ($t = $denni_od; $t + $trvani_min * 60 <= $denni_do; $t += $slot) {
$ok = true;
for ($s = $t; $s < $t + $trvani_min * 60; $s += $slot) {
if (in_array(date('H:i', $s), $obsazene)) { $ok = false; break; }
}
if ($ok) $volne[] = date('H:i', $t);
}
return $volne;
}
function je_blokovany_den(string $datum): bool {
$stmt = db()->prepare("
SELECT id FROM blokovane_terminy
WHERE datum_od <= ? AND datum_do >= ? LIMIT 1
");
$stmt->execute([$datum, $datum]);
return (bool) $stmt->fetch();
}