2026-03-30 22:52:37 +00:00

687 lines
28 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Plugin Name: Nazar Kebap MVP
* Description: Restaurant landing page styling and simple table reservation workflow for Nazar Kebap - Gasthaus.
* Version: 1.2.0
* Author: OpenAI Codex
*/
if (!defined('ABSPATH')) {
exit;
}
class Nazar_Kebap_MVP {
const POST_TYPE = 'nazar_reservation';
const STATUS_META = '_reservation_status';
const AVAILABILITY_NONCE = 'nazar_reservation_availability';
const OPENING_TIME = '09:00';
const LAST_BOOKING_TIME = '23:30';
const TIME_STEP_MINUTES = 5;
public function __construct() {
add_action('init', [$this, 'register_post_type']);
add_action('init', [$this, 'register_shortcodes']);
add_action('wp_enqueue_scripts', [$this, 'enqueue_assets']);
add_action('admin_post_nazar_reserve_table', [$this, 'handle_reservation']);
add_action('admin_post_nopriv_nazar_reserve_table', [$this, 'handle_reservation']);
add_action('wp_ajax_nazar_get_available_times', [$this, 'ajax_get_available_times']);
add_action('wp_ajax_nopriv_nazar_get_available_times', [$this, 'ajax_get_available_times']);
add_filter('body_class', [$this, 'body_classes']);
add_filter('manage_' . self::POST_TYPE . '_posts_columns', [$this, 'admin_columns']);
add_action('manage_' . self::POST_TYPE . '_posts_custom_column', [$this, 'render_admin_columns'], 10, 2);
add_action('add_meta_boxes', [$this, 'add_meta_boxes']);
add_action('save_post_' . self::POST_TYPE, [$this, 'save_reservation_meta']);
}
public function register_post_type() {
register_post_type(self::POST_TYPE, [
'labels' => [
'name' => 'Reservierungen',
'singular_name' => 'Reservierung',
'menu_name' => 'Reservierungen',
'add_new_item' => 'Neue Reservierung',
'edit_item' => 'Reservierung bearbeiten',
'view_item' => 'Reservierung ansehen',
'search_items' => 'Reservierungen suchen',
],
'public' => false,
'show_ui' => true,
'show_in_menu' => true,
'menu_icon' => 'dashicons-calendar-alt',
'supports' => ['title'],
'map_meta_cap' => true,
]);
}
public function register_shortcodes() {
add_shortcode('nazar_reservation_form', [$this, 'reservation_form_shortcode']);
}
public function enqueue_assets() {
$plugin_url = plugin_dir_url(__FILE__);
$plugin_path = plugin_dir_path(__FILE__);
wp_enqueue_style(
'nazar-kebap-mvp',
$plugin_url . 'assets/site.css',
[],
filemtime($plugin_path . 'assets/site.css')
);
wp_enqueue_script(
'nazar-kebap-reservations',
$plugin_url . 'assets/reservation.js',
[],
filemtime($plugin_path . 'assets/reservation.js'),
true
);
wp_localize_script('nazar-kebap-reservations', 'nazarReservationData', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce(self::AVAILABILITY_NONCE),
'messages' => [
'chooseDateAndParty' => 'Bitte wählen Sie zuerst Datum und Personenzahl.',
'loading' => 'Verfügbare Uhrzeiten werden geladen …',
'empty' => 'Für diese Auswahl ist aktuell keine freie Uhrzeit verfügbar.',
'error' => 'Die verfügbaren Uhrzeiten konnten gerade nicht geladen werden. Bitte versuchen Sie es erneut.',
],
]);
}
public function body_classes($classes) {
$classes[] = 'nazar-site';
return $classes;
}
public function reservation_form_shortcode() {
$status = isset($_GET['reservation']) ? sanitize_key(wp_unslash($_GET['reservation'])) : '';
$messages = [
'success' => 'Danke! Ihre Reservierungsanfrage wurde erfolgreich übermittelt. Sie erhalten in Kürze eine Bestätigung per E-Mail mit allen Buchungsdetails.',
'error' => 'Bitte prüfen Sie Ihre Eingaben. Alle Pflichtfelder müssen ausgefüllt sein.',
'conflict' => 'Diese Uhrzeit ist leider nicht mehr verfügbar. Bitte wählen Sie eine andere freie Uhrzeit.',
];
ob_start();
?>
<div class="nazar-form-wrap">
<?php if ($status && isset($messages[$status])) : ?>
<div class="nazar-alert nazar-alert-<?php echo esc_attr($status === 'conflict' ? 'error' : $status); ?>">
<?php echo esc_html($messages[$status]); ?>
</div>
<?php endif; ?>
<form class="nazar-reservation-form" method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" data-availability-form>
<input type="hidden" name="action" value="nazar_reserve_table">
<?php wp_nonce_field('nazar_reserve_table', 'nazar_reserve_nonce'); ?>
<div class="nazar-form-grid">
<label>
<span>Name *</span>
<input type="text" name="guest_name" required>
</label>
<label>
<span>Telefon *</span>
<input type="tel" name="guest_phone" required>
</label>
<label>
<span>E-Mail *</span>
<input type="email" name="guest_email" required>
</label>
<label>
<span>Personen *</span>
<select name="party_size" required data-party-size>
<option value="">Bitte wählen</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8+">8+</option>
</select>
</label>
<label>
<span>Datum *</span>
<input type="date" name="reservation_date" min="<?php echo esc_attr(wp_date('Y-m-d')); ?>" required data-reservation-date>
</label>
<label>
<span>Uhrzeit *</span>
<select name="reservation_time" required data-reservation-time disabled>
<option value="">Bitte erst Datum und Personen wählen</option>
</select>
</label>
</div>
<p class="nazar-availability-note" data-availability-note>Bitte wählen Sie zuerst Datum und Personenzahl.</p>
<label>
<span>Hinweise</span>
<textarea name="reservation_notes" rows="4" placeholder="z. B. Kinderstuhl, ruhiger Tisch, Allergien"></textarea>
</label>
<p class="nazar-form-note">Reservierungen werden direkt gegen bestehende Buchungen geprüft. Gesperrte Zeiten richten sich nach der Personenzahl: 1 Person = 10 Min., 2 Personen = 15 Min., 34 Personen = 30 Min., ab 5 Personen = 60 Min.</p>
<button type="submit" class="wp-element-button">Tisch anfragen</button>
</form>
</div>
<?php
return ob_get_clean();
}
public function handle_reservation() {
$redirect_url = wp_get_referer() ?: home_url('/reservierung/');
if (!isset($_POST['nazar_reserve_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nazar_reserve_nonce'])), 'nazar_reserve_table')) {
wp_safe_redirect(add_query_arg('reservation', 'error', $redirect_url));
exit;
}
$fields = [
'guest_name' => sanitize_text_field(wp_unslash($_POST['guest_name'] ?? '')),
'guest_phone' => sanitize_text_field(wp_unslash($_POST['guest_phone'] ?? '')),
'guest_email' => sanitize_email(wp_unslash($_POST['guest_email'] ?? '')),
'party_size' => sanitize_text_field(wp_unslash($_POST['party_size'] ?? '')),
'reservation_date' => sanitize_text_field(wp_unslash($_POST['reservation_date'] ?? '')),
'reservation_time' => sanitize_text_field(wp_unslash($_POST['reservation_time'] ?? '')),
'reservation_notes' => sanitize_textarea_field(wp_unslash($_POST['reservation_notes'] ?? '')),
];
if (!$fields['guest_name'] || !$fields['guest_phone'] || !$fields['guest_email'] || !$fields['party_size'] || !$fields['reservation_date'] || !$fields['reservation_time']) {
wp_safe_redirect(add_query_arg('reservation', 'error', $redirect_url));
exit;
}
$fields['reservation_time'] = $this->normalize_time($fields['reservation_time']);
if (!$fields['reservation_time'] || !$this->is_time_available($fields['reservation_date'], $fields['reservation_time'], $fields['party_size'])) {
wp_safe_redirect(add_query_arg('reservation', 'conflict', $redirect_url));
exit;
}
$title = sprintf(
'Reservierung %s %s %s',
$fields['guest_name'],
$fields['reservation_date'],
$fields['reservation_time']
);
$post_id = wp_insert_post([
'post_type' => self::POST_TYPE,
'post_status' => 'publish',
'post_title' => $title,
'meta_input' => [
'_guest_name' => $fields['guest_name'],
'_guest_phone' => $fields['guest_phone'],
'_guest_email' => $fields['guest_email'],
'_party_size' => $fields['party_size'],
'_reservation_date' => $fields['reservation_date'],
'_reservation_time' => $fields['reservation_time'],
'_reservation_notes' => $fields['reservation_notes'],
'_reservation_duration' => $this->get_duration_minutes($fields['party_size']),
self::STATUS_META => 'neu',
],
]);
if (is_wp_error($post_id) || !$post_id) {
wp_safe_redirect(add_query_arg('reservation', 'error', $redirect_url));
exit;
}
$notification_results = $this->send_new_reservation_notifications($post_id, $fields);
update_post_meta($post_id, '_admin_notification_sent', $notification_results['admin'] ? 'yes' : 'no');
update_post_meta($post_id, '_customer_notification_sent', $notification_results['customer'] ? 'yes' : 'no');
update_post_meta($post_id, '_notification_sent_at', current_time('mysql'));
wp_safe_redirect(add_query_arg('reservation', 'success', home_url('/reservierung/')));
exit;
}
public function ajax_get_available_times() {
check_ajax_referer(self::AVAILABILITY_NONCE, 'nonce');
$date = sanitize_text_field(wp_unslash($_POST['reservation_date'] ?? ''));
$party_size = sanitize_text_field(wp_unslash($_POST['party_size'] ?? ''));
if (!$date || !$party_size) {
wp_send_json_error([
'message' => 'Datum und Personenzahl sind erforderlich.',
], 400);
}
$times = $this->get_available_time_slots($date, $party_size);
$duration = $this->get_duration_minutes($party_size);
wp_send_json_success([
'times' => $times,
'duration' => $duration,
'message' => sprintf(
'Für %s blockiert eine Reservierung %d Minuten. Es werden nur freie Uhrzeiten angezeigt.',
$party_size,
$duration
),
]);
}
public function admin_columns($columns) {
return [
'cb' => $columns['cb'],
'title' => 'Anfrage',
'reservation_datetime' => 'Datum & Uhrzeit',
'party_size' => 'Personen',
'contact' => 'Kontakt',
'reservation_status' => 'Status',
'date' => 'Eingegangen',
];
}
public function render_admin_columns($column, $post_id) {
switch ($column) {
case 'reservation_datetime':
echo esc_html(get_post_meta($post_id, '_reservation_date', true));
echo '<br>';
echo esc_html(get_post_meta($post_id, '_reservation_time', true));
break;
case 'party_size':
echo esc_html(get_post_meta($post_id, '_party_size', true));
break;
case 'contact':
echo esc_html(get_post_meta($post_id, '_guest_name', true));
echo '<br>';
echo esc_html(get_post_meta($post_id, '_guest_phone', true));
$email = get_post_meta($post_id, '_guest_email', true);
if ($email) {
echo '<br>' . esc_html($email);
}
break;
case 'reservation_status':
echo esc_html(ucfirst(get_post_meta($post_id, self::STATUS_META, true) ?: 'neu'));
break;
}
}
public function add_meta_boxes() {
add_meta_box(
'nazar_reservation_details',
'Reservierungsdetails',
[$this, 'render_meta_box'],
self::POST_TYPE,
'normal',
'high'
);
}
public function render_meta_box($post) {
wp_nonce_field('nazar_save_reservation', 'nazar_save_reservation_nonce');
$status = get_post_meta($post->ID, self::STATUS_META, true) ?: 'neu';
?>
<table class="form-table">
<tr><th>Name</th><td><?php echo esc_html(get_post_meta($post->ID, '_guest_name', true)); ?></td></tr>
<tr><th>Telefon</th><td><?php echo esc_html(get_post_meta($post->ID, '_guest_phone', true)); ?></td></tr>
<tr><th>E-Mail</th><td><?php echo esc_html(get_post_meta($post->ID, '_guest_email', true)); ?></td></tr>
<tr><th>Datum</th><td><?php echo esc_html(get_post_meta($post->ID, '_reservation_date', true)); ?></td></tr>
<tr><th>Uhrzeit</th><td><?php echo esc_html(get_post_meta($post->ID, '_reservation_time', true)); ?></td></tr>
<tr><th>Personen</th><td><?php echo esc_html(get_post_meta($post->ID, '_party_size', true)); ?></td></tr>
<tr><th>Blockiert bis</th><td><?php echo esc_html($this->get_blocked_until_label($post->ID)); ?></td></tr>
<tr><th>Admin-E-Mail</th><td><?php echo esc_html($this->humanize_notification_status(get_post_meta($post->ID, '_admin_notification_sent', true))); ?></td></tr>
<tr><th>Kunden-E-Mail</th><td><?php echo esc_html($this->humanize_notification_status(get_post_meta($post->ID, '_customer_notification_sent', true))); ?></td></tr>
<tr><th>Status-E-Mail</th><td><?php echo esc_html($this->humanize_notification_status(get_post_meta($post->ID, '_status_notification_sent', true))); ?></td></tr>
<tr><th>Hinweise</th><td><?php echo nl2br(esc_html(get_post_meta($post->ID, '_reservation_notes', true))); ?></td></tr>
<tr>
<th><label for="nazar_reservation_status">Status</label></th>
<td>
<select name="nazar_reservation_status" id="nazar_reservation_status">
<?php foreach (['neu', 'bestätigt', 'abgelehnt', 'erledigt'] as $option) : ?>
<option value="<?php echo esc_attr($option); ?>" <?php selected($status, $option); ?>><?php echo esc_html(ucfirst($option)); ?></option>
<?php endforeach; ?>
</select>
</td>
</tr>
</table>
<?php
}
public function save_reservation_meta($post_id) {
if (!isset($_POST['nazar_save_reservation_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nazar_save_reservation_nonce'])), 'nazar_save_reservation')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
$status = sanitize_text_field(wp_unslash($_POST['nazar_reservation_status'] ?? 'neu'));
$previous_status = get_post_meta($post_id, self::STATUS_META, true) ?: 'neu';
update_post_meta($post_id, self::STATUS_META, $status);
if ($status !== $previous_status) {
$status_sent = $this->send_status_update_notification($post_id, $status, $previous_status);
update_post_meta($post_id, '_status_notification_sent', $status_sent ? 'yes' : 'no');
update_post_meta($post_id, '_status_notification_sent_at', current_time('mysql'));
}
}
public function get_available_time_slots($date, $party_size) {
if (!$this->is_valid_reservation_date($date) || !$this->parse_party_size($party_size)) {
return [];
}
$slots = [];
$start = $this->date_time_to_timestamp($date, self::OPENING_TIME);
$end = $this->date_time_to_timestamp($date, self::LAST_BOOKING_TIME);
if (!$start || !$end || $start > $end) {
return [];
}
for ($cursor = $start; $cursor <= $end; $cursor += self::TIME_STEP_MINUTES * MINUTE_IN_SECONDS) {
$time = wp_date('H:i', $cursor);
if ($this->is_time_available($date, $time, $party_size)) {
$slots[] = [
'value' => $time,
'label' => $time,
];
}
}
return $slots;
}
public function is_time_available($date, $time, $party_size, $exclude_post_id = 0) {
if (!$this->is_valid_reservation_date($date)) {
return false;
}
$time = $this->normalize_time($time);
$party_count = $this->parse_party_size($party_size);
if (!$time || !$party_count) {
return false;
}
$requested_start = $this->date_time_to_timestamp($date, $time);
$requested_end = $requested_start ? $requested_start + ($this->get_duration_minutes($party_size) * MINUTE_IN_SECONDS) : false;
if (!$requested_start || !$requested_end) {
return false;
}
foreach ($this->get_reservations_for_date($date, $exclude_post_id) as $reservation) {
if (($reservation['status'] ?? '') === 'abgelehnt') {
continue;
}
if (!$reservation['start'] || !$reservation['end']) {
continue;
}
if ($requested_start < $reservation['end'] && $requested_end > $reservation['start']) {
return false;
}
}
return true;
}
private function send_new_reservation_notifications($post_id, $fields) {
$admin_email = sanitize_email(get_option('admin_email'));
$admin_sent = false;
$customer_sent = false;
$details = $this->get_reservation_email_details($post_id, $fields);
if ($admin_email) {
$subject = sprintf('Neue Reservierung: %s am %s um %s', $details['name'], $details['date_label'], $details['time_label']);
$message = implode("
", [
'Eine neue Reservierungsanfrage wurde über die Website gesendet.',
'',
'Name: ' . $details['name'],
'Telefon: ' . $details['phone'],
'E-Mail: ' . $details['email'],
'Personen: ' . $details['party_size'],
'Datum: ' . $details['date_label'],
'Uhrzeit: ' . $details['time_label'],
'Blockiert bis: ' . $details['blocked_until_label'],
'Hinweise: ' . ($details['notes'] ?: 'Keine'),
'',
'Im Admin bearbeiten: ' . admin_url('post.php?post=' . $post_id . '&action=edit'),
]);
$admin_sent = wp_mail($admin_email, $subject, $message, $this->get_email_headers());
}
if ($details['email']) {
$subject = sprintf('Ihre Reservierungsanfrage bei %s', get_bloginfo('name'));
$message = implode("
", [
'Vielen Dank für Ihre Reservierungsanfrage bei ' . get_bloginfo('name') . '.',
'',
'Ihre Buchungsdaten:',
'Name: ' . $details['name'],
'Telefon: ' . $details['phone'],
'E-Mail: ' . $details['email'],
'Personen: ' . $details['party_size'],
'Datum: ' . $details['date_label'],
'Uhrzeit: ' . $details['time_label'],
'Reservierungsdauer: ' . $details['duration_label'],
'Hinweise: ' . ($details['notes'] ?: 'Keine'),
'',
'Falls wir Rückfragen haben, melden wir uns unter der angegebenen Telefonnummer oder E-Mail-Adresse.',
'Telefon Restaurant: +49 781 96643005',
'Adresse: Saarlandstraße 2, 77652 Offenburg',
]);
$customer_sent = wp_mail($details['email'], $subject, $message, $this->get_email_headers());
}
return [
'admin' => (bool) $admin_sent,
'customer' => (bool) $customer_sent,
];
}
private function send_status_update_notification($post_id, $new_status, $old_status) {
$email = sanitize_email(get_post_meta($post_id, '_guest_email', true));
if (!$email) {
return false;
}
$details = $this->get_reservation_email_details($post_id);
$status_labels = [
'neu' => 'neu',
'bestätigt' => 'bestätigt',
'abgelehnt' => 'abgelehnt',
'erledigt' => 'erledigt',
];
$new_label = $status_labels[$new_status] ?? $new_status;
$old_label = $status_labels[$old_status] ?? $old_status;
$subject = sprintf('Update zu Ihrer Reservierung bei %s', get_bloginfo('name'));
$message = implode("
", [
'Es gibt ein Update zu Ihrer Reservierung bei ' . get_bloginfo('name') . '.',
'',
'Bisheriger Status: ' . $old_label,
'Neuer Status: ' . $new_label,
'',
'Name: ' . $details['name'],
'Personen: ' . $details['party_size'],
'Datum: ' . $details['date_label'],
'Uhrzeit: ' . $details['time_label'],
'',
'Bei Fragen erreichen Sie uns unter +49 781 96643005.',
]);
return (bool) wp_mail($email, $subject, $message, $this->get_email_headers());
}
private function get_reservation_email_details($post_id = 0, $fields = []) {
$name = $fields['guest_name'] ?? get_post_meta($post_id, '_guest_name', true);
$phone = $fields['guest_phone'] ?? get_post_meta($post_id, '_guest_phone', true);
$email = $fields['guest_email'] ?? get_post_meta($post_id, '_guest_email', true);
$party_size = $fields['party_size'] ?? get_post_meta($post_id, '_party_size', true);
$date = $fields['reservation_date'] ?? get_post_meta($post_id, '_reservation_date', true);
$time = $fields['reservation_time'] ?? get_post_meta($post_id, '_reservation_time', true);
$notes = $fields['reservation_notes'] ?? get_post_meta($post_id, '_reservation_notes', true);
$date_label = $date ? wp_date('d.m.Y', strtotime($date)) : '';
$time_label = $this->normalize_time($time) ?: '';
$duration = $this->get_duration_minutes($party_size);
$blocked_until_label = '';
if ($date && $time_label) {
$start = $this->date_time_to_timestamp($date, $time_label);
if ($start) {
$blocked_until_label = wp_date('d.m.Y H:i', $start + ($duration * MINUTE_IN_SECONDS));
}
}
return [
'name' => $name ?: '',
'phone' => $phone ?: '',
'email' => $email ?: '',
'party_size' => $party_size ?: '',
'date_label' => $date_label,
'time_label' => $time_label,
'duration_label' => $duration ? ($duration . ' Minuten') : '',
'blocked_until_label' => $blocked_until_label,
'notes' => $notes ?: '',
];
}
private function get_email_headers() {
$blogname = wp_specialchars_decode(get_bloginfo('name'), ENT_QUOTES);
$admin_email = sanitize_email(get_option('admin_email'));
return [
'Content-Type: text/plain; charset=UTF-8',
sprintf('Reply-To: %s <%s>', $blogname, $admin_email),
];
}
private function humanize_notification_status($status) {
return $status === 'yes' ? 'Gesendet' : ($status === 'no' ? 'Fehlgeschlagen' : '');
}
private function get_reservations_for_date($date, $exclude_post_id = 0) {
$query = new WP_Query([
'post_type' => self::POST_TYPE,
'post_status' => 'publish',
'posts_per_page' => -1,
'fields' => 'ids',
'meta_key' => '_reservation_date',
'meta_value' => $date,
'orderby' => 'meta_value',
'order' => 'ASC',
'post__not_in' => $exclude_post_id ? [(int) $exclude_post_id] : [],
]);
$reservations = [];
foreach ($query->posts as $post_id) {
$time = $this->normalize_time(get_post_meta($post_id, '_reservation_time', true));
$party_size = get_post_meta($post_id, '_party_size', true);
$start = $time ? $this->date_time_to_timestamp($date, $time) : false;
$duration = $this->get_duration_minutes($party_size);
$reservations[] = [
'post_id' => $post_id,
'status' => get_post_meta($post_id, self::STATUS_META, true) ?: 'neu',
'time' => $time,
'party_size' => $party_size,
'duration' => $duration,
'start' => $start,
'end' => $start ? $start + ($duration * MINUTE_IN_SECONDS) : false,
];
}
wp_reset_postdata();
return $reservations;
}
private function get_duration_minutes($party_size) {
$count = $this->parse_party_size($party_size);
if ($count <= 0) {
return 0;
}
if ($count === 1) {
return 10;
}
if ($count === 2) {
return 15;
}
if ($count <= 4) {
return 30;
}
return 60;
}
private function parse_party_size($party_size) {
if (is_numeric($party_size)) {
return max(0, (int) $party_size);
}
if (is_string($party_size) && preg_match('/^(\d+)\+?$/', $party_size, $matches)) {
return max(0, (int) $matches[1]);
}
return 0;
}
private function normalize_time($time) {
if (!is_string($time) || $time === '') {
return '';
}
$date_time = date_create_from_format('H:i', $time, wp_timezone()) ?: date_create_from_format('H:i:s', $time, wp_timezone());
if (!$date_time) {
return '';
}
return $date_time->format('H:i');
}
private function is_valid_reservation_date($date) {
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', (string) $date)) {
return false;
}
$candidate = date_create_immutable_from_format('Y-m-d', $date, wp_timezone());
return $candidate && $candidate->format('Y-m-d') === $date;
}
private function date_time_to_timestamp($date, $time) {
$date_time = date_create_immutable_from_format('Y-m-d H:i', $date . ' ' . $time, wp_timezone());
return $date_time ? $date_time->getTimestamp() : false;
}
private function get_blocked_until_label($post_id) {
$date = get_post_meta($post_id, '_reservation_date', true);
$time = $this->normalize_time(get_post_meta($post_id, '_reservation_time', true));
$party_size = get_post_meta($post_id, '_party_size', true);
$start = ($date && $time) ? $this->date_time_to_timestamp($date, $time) : false;
if (!$start) {
return '';
}
$end = $start + ($this->get_duration_minutes($party_size) * MINUTE_IN_SECONDS);
return wp_date('Y-m-d H:i', $end);
}
}
$GLOBALS['nazar_kebap_mvp'] = new Nazar_Kebap_MVP();