2026-01-31 14:37:48 +01:00
|
|
|
<?php
|
|
|
|
|
/**
|
|
|
|
|
* Email notifier for bookings.
|
|
|
|
|
*
|
|
|
|
|
* Handles sending email notifications for booking events.
|
|
|
|
|
*
|
|
|
|
|
* @package Magdev\WpBnb\Booking
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
declare( strict_types=1 );
|
|
|
|
|
|
|
|
|
|
namespace Magdev\WpBnb\Booking;
|
|
|
|
|
|
|
|
|
|
use Magdev\WpBnb\PostTypes\Booking;
|
2026-01-31 14:59:43 +01:00
|
|
|
use Magdev\WpBnb\PostTypes\Guest;
|
2026-01-31 14:37:48 +01:00
|
|
|
use Magdev\WpBnb\PostTypes\Room;
|
|
|
|
|
use Magdev\WpBnb\Pricing\Calculator;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* EmailNotifier class.
|
|
|
|
|
*/
|
|
|
|
|
final class EmailNotifier {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize the email notifier.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public static function init(): void {
|
|
|
|
|
add_action( 'wp_bnb_booking_status_changed', array( self::class, 'on_status_change' ), 10, 3 );
|
|
|
|
|
add_action( 'save_post_' . Booking::POST_TYPE, array( self::class, 'on_booking_created' ), 20, 2 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle status change event.
|
|
|
|
|
*
|
|
|
|
|
* @param int $booking_id Booking post ID.
|
|
|
|
|
* @param string $old_status Previous status.
|
|
|
|
|
* @param string $new_status New status.
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public static function on_status_change( int $booking_id, string $old_status, string $new_status ): void {
|
|
|
|
|
switch ( $new_status ) {
|
|
|
|
|
case 'confirmed':
|
|
|
|
|
self::send_guest_confirmation( $booking_id );
|
|
|
|
|
self::send_admin_confirmation( $booking_id );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'cancelled':
|
|
|
|
|
self::send_cancellation( $booking_id );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle booking created event.
|
|
|
|
|
*
|
|
|
|
|
* @param int $post_id Post ID.
|
|
|
|
|
* @param \WP_Post $post Post object.
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public static function on_booking_created( int $post_id, \WP_Post $post ): void {
|
|
|
|
|
// Skip if autosave or revision.
|
|
|
|
|
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( wp_is_post_revision( $post_id ) ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if this is a new booking (created in the last 30 seconds).
|
|
|
|
|
$created = get_post_time( 'U', true, $post_id );
|
|
|
|
|
if ( time() - $created > 30 ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if we've already sent this notification.
|
|
|
|
|
$sent = get_post_meta( $post_id, '_bnb_booking_new_email_sent', true );
|
|
|
|
|
if ( $sent ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mark as sent before sending to prevent duplicates.
|
|
|
|
|
update_post_meta( $post_id, '_bnb_booking_new_email_sent', '1' );
|
|
|
|
|
|
|
|
|
|
// Send admin notification for new booking.
|
|
|
|
|
self::send_admin_new_booking( $post_id );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Send new booking notification to admin.
|
|
|
|
|
*
|
|
|
|
|
* @param int $booking_id Booking post ID.
|
|
|
|
|
* @return bool Whether email was sent.
|
|
|
|
|
*/
|
|
|
|
|
public static function send_admin_new_booking( int $booking_id ): bool {
|
|
|
|
|
$booking = get_post( $booking_id );
|
|
|
|
|
if ( ! $booking ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$data = self::get_booking_data( $booking_id );
|
|
|
|
|
$to = get_option( 'admin_email' );
|
|
|
|
|
$subject = sprintf(
|
|
|
|
|
/* translators: 1: Site name, 2: Booking reference */
|
|
|
|
|
__( '[%1$s] New Booking: %2$s', 'wp-bnb' ),
|
|
|
|
|
get_bloginfo( 'name' ),
|
|
|
|
|
$data['booking_reference']
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$message = self::get_email_template( 'admin-new-booking', $data );
|
|
|
|
|
|
|
|
|
|
return self::send_email( $to, $subject, $message );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Send confirmation email to guest.
|
|
|
|
|
*
|
|
|
|
|
* @param int $booking_id Booking post ID.
|
|
|
|
|
* @return bool Whether email was sent.
|
|
|
|
|
*/
|
|
|
|
|
public static function send_guest_confirmation( int $booking_id ): bool {
|
|
|
|
|
$data = self::get_booking_data( $booking_id );
|
|
|
|
|
|
|
|
|
|
if ( empty( $data['guest_email'] ) ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$subject = sprintf(
|
|
|
|
|
/* translators: 1: Site name, 2: Booking reference */
|
|
|
|
|
__( '[%1$s] Booking Confirmed: %2$s', 'wp-bnb' ),
|
|
|
|
|
get_bloginfo( 'name' ),
|
|
|
|
|
$data['booking_reference']
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$message = self::get_email_template( 'booking-confirmed', $data );
|
|
|
|
|
|
|
|
|
|
return self::send_email( $data['guest_email'], $subject, $message );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Send confirmation notification to admin.
|
|
|
|
|
*
|
|
|
|
|
* @param int $booking_id Booking post ID.
|
|
|
|
|
* @return bool Whether email was sent.
|
|
|
|
|
*/
|
|
|
|
|
public static function send_admin_confirmation( int $booking_id ): bool {
|
|
|
|
|
$data = self::get_booking_data( $booking_id );
|
|
|
|
|
$to = get_option( 'admin_email' );
|
|
|
|
|
$subject = sprintf(
|
|
|
|
|
/* translators: 1: Site name, 2: Booking reference */
|
|
|
|
|
__( '[%1$s] Booking Confirmed: %2$s', 'wp-bnb' ),
|
|
|
|
|
get_bloginfo( 'name' ),
|
|
|
|
|
$data['booking_reference']
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$message = self::get_email_template( 'admin-booking-confirmed', $data );
|
|
|
|
|
|
|
|
|
|
return self::send_email( $to, $subject, $message );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Send cancellation email.
|
|
|
|
|
*
|
|
|
|
|
* @param int $booking_id Booking post ID.
|
|
|
|
|
* @return bool Whether emails were sent.
|
|
|
|
|
*/
|
|
|
|
|
public static function send_cancellation( int $booking_id ): bool {
|
|
|
|
|
$data = self::get_booking_data( $booking_id );
|
|
|
|
|
$result = true;
|
|
|
|
|
|
|
|
|
|
// Send to admin.
|
|
|
|
|
$admin_subject = sprintf(
|
|
|
|
|
/* translators: 1: Site name, 2: Booking reference */
|
|
|
|
|
__( '[%1$s] Booking Cancelled: %2$s', 'wp-bnb' ),
|
|
|
|
|
get_bloginfo( 'name' ),
|
|
|
|
|
$data['booking_reference']
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$admin_message = self::get_email_template( 'admin-booking-cancelled', $data );
|
|
|
|
|
$result = self::send_email( get_option( 'admin_email' ), $admin_subject, $admin_message ) && $result;
|
|
|
|
|
|
|
|
|
|
// Send to guest if email exists.
|
|
|
|
|
if ( ! empty( $data['guest_email'] ) ) {
|
|
|
|
|
$guest_subject = sprintf(
|
|
|
|
|
/* translators: 1: Site name, 2: Booking reference */
|
|
|
|
|
__( '[%1$s] Booking Cancelled: %2$s', 'wp-bnb' ),
|
|
|
|
|
get_bloginfo( 'name' ),
|
|
|
|
|
$data['booking_reference']
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$guest_message = self::get_email_template( 'booking-cancelled', $data );
|
|
|
|
|
$result = self::send_email( $data['guest_email'], $guest_subject, $guest_message ) && $result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get booking data for email templates.
|
|
|
|
|
*
|
|
|
|
|
* @param int $booking_id Booking post ID.
|
|
|
|
|
* @return array Booking data.
|
|
|
|
|
*/
|
|
|
|
|
private static function get_booking_data( int $booking_id ): array {
|
2026-01-31 14:59:43 +01:00
|
|
|
$booking = get_post( $booking_id );
|
|
|
|
|
$room = Booking::get_room( $booking_id );
|
2026-01-31 14:37:48 +01:00
|
|
|
$building = Booking::get_building( $booking_id );
|
|
|
|
|
|
|
|
|
|
$check_in = get_post_meta( $booking_id, '_bnb_booking_check_in', true );
|
|
|
|
|
$check_out = get_post_meta( $booking_id, '_bnb_booking_check_out', true );
|
|
|
|
|
$status = get_post_meta( $booking_id, '_bnb_booking_status', true );
|
|
|
|
|
$price = get_post_meta( $booking_id, '_bnb_booking_calculated_price', true );
|
|
|
|
|
$adults = get_post_meta( $booking_id, '_bnb_booking_adults', true );
|
|
|
|
|
$children = get_post_meta( $booking_id, '_bnb_booking_children', true );
|
|
|
|
|
|
|
|
|
|
$nights = 0;
|
|
|
|
|
if ( $check_in && $check_out ) {
|
|
|
|
|
$nights = Booking::calculate_nights( $check_in, $check_out );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$statuses = Booking::get_booking_statuses();
|
|
|
|
|
|
2026-01-31 14:59:43 +01:00
|
|
|
// Get guest data - prefer Guest CPT if linked, fallback to booking meta.
|
|
|
|
|
$guest_data = self::get_guest_data( $booking_id );
|
|
|
|
|
|
|
|
|
|
return array(
|
|
|
|
|
'booking_id' => $booking_id,
|
|
|
|
|
'booking_reference' => $booking ? $booking->post_title : '',
|
|
|
|
|
'guest_name' => $guest_data['name'],
|
|
|
|
|
'guest_first_name' => $guest_data['first_name'],
|
|
|
|
|
'guest_last_name' => $guest_data['last_name'],
|
|
|
|
|
'guest_email' => $guest_data['email'],
|
|
|
|
|
'guest_phone' => $guest_data['phone'],
|
|
|
|
|
'guest_notes' => $guest_data['notes'],
|
|
|
|
|
'guest_full_address' => $guest_data['full_address'],
|
|
|
|
|
'adults' => $adults ?: 1,
|
|
|
|
|
'children' => $children ?: 0,
|
|
|
|
|
'room_name' => $room ? $room->post_title : '',
|
|
|
|
|
'room_id' => $room ? $room->ID : 0,
|
|
|
|
|
'building_name' => $building ? $building->post_title : '',
|
|
|
|
|
'building_id' => $building ? $building->ID : 0,
|
|
|
|
|
'check_in_date' => $check_in ? wp_date( get_option( 'date_format' ), strtotime( $check_in ) ) : '',
|
|
|
|
|
'check_out_date' => $check_out ? wp_date( get_option( 'date_format' ), strtotime( $check_out ) ) : '',
|
|
|
|
|
'check_in_raw' => $check_in,
|
|
|
|
|
'check_out_raw' => $check_out,
|
|
|
|
|
'nights' => $nights,
|
|
|
|
|
'total_price' => $price ? Calculator::formatPrice( (float) $price ) : '',
|
|
|
|
|
'status' => $statuses[ $status ] ?? $status,
|
|
|
|
|
'status_raw' => $status,
|
|
|
|
|
'site_name' => get_bloginfo( 'name' ),
|
|
|
|
|
'site_url' => home_url(),
|
|
|
|
|
'admin_email' => get_option( 'admin_email' ),
|
|
|
|
|
'booking_url' => admin_url( 'post.php?post=' . $booking_id . '&action=edit' ),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get guest data from Guest CPT or booking meta.
|
|
|
|
|
*
|
|
|
|
|
* @param int $booking_id Booking post ID.
|
|
|
|
|
* @return array Guest data with keys: name, first_name, last_name, email, phone, notes, full_address.
|
|
|
|
|
*/
|
|
|
|
|
private static function get_guest_data( int $booking_id ): array {
|
|
|
|
|
$guest_id = get_post_meta( $booking_id, '_bnb_booking_guest_id', true );
|
|
|
|
|
|
|
|
|
|
// Try to get data from Guest CPT.
|
|
|
|
|
if ( $guest_id ) {
|
|
|
|
|
$guest = get_post( $guest_id );
|
|
|
|
|
if ( $guest && Guest::POST_TYPE === $guest->post_type ) {
|
|
|
|
|
$first_name = get_post_meta( $guest_id, '_bnb_guest_first_name', true );
|
|
|
|
|
$last_name = get_post_meta( $guest_id, '_bnb_guest_last_name', true );
|
|
|
|
|
|
|
|
|
|
return array(
|
|
|
|
|
'name' => Guest::get_full_name( $guest_id ),
|
|
|
|
|
'first_name' => $first_name,
|
|
|
|
|
'last_name' => $last_name,
|
|
|
|
|
'email' => get_post_meta( $guest_id, '_bnb_guest_email', true ),
|
|
|
|
|
'phone' => get_post_meta( $guest_id, '_bnb_guest_phone', true ),
|
|
|
|
|
'notes' => get_post_meta( $guest_id, '_bnb_guest_notes', true ),
|
|
|
|
|
'full_address' => Guest::get_formatted_address( $guest_id ),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fallback to booking meta (legacy bookings).
|
|
|
|
|
$guest_name = get_post_meta( $booking_id, '_bnb_booking_guest_name', true );
|
|
|
|
|
|
|
|
|
|
// Try to split name into first/last for legacy data.
|
|
|
|
|
$name_parts = explode( ' ', $guest_name, 2 );
|
|
|
|
|
$first_name = $name_parts[0] ?? '';
|
|
|
|
|
$last_name = $name_parts[1] ?? '';
|
|
|
|
|
|
2026-01-31 14:37:48 +01:00
|
|
|
return array(
|
2026-01-31 14:59:43 +01:00
|
|
|
'name' => $guest_name,
|
|
|
|
|
'first_name' => $first_name,
|
|
|
|
|
'last_name' => $last_name,
|
|
|
|
|
'email' => get_post_meta( $booking_id, '_bnb_booking_guest_email', true ),
|
|
|
|
|
'phone' => get_post_meta( $booking_id, '_bnb_booking_guest_phone', true ),
|
|
|
|
|
'notes' => get_post_meta( $booking_id, '_bnb_booking_guest_notes', true ),
|
|
|
|
|
'full_address' => '', // Legacy bookings don't have full address.
|
2026-01-31 14:37:48 +01:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get email template with placeholders replaced.
|
|
|
|
|
*
|
|
|
|
|
* @param string $template_name Template name.
|
|
|
|
|
* @param array $data Template data.
|
|
|
|
|
* @return string HTML email content.
|
|
|
|
|
*/
|
|
|
|
|
private static function get_email_template( string $template_name, array $data ): string {
|
|
|
|
|
$template = self::get_template_content( $template_name );
|
|
|
|
|
|
|
|
|
|
// Replace placeholders.
|
|
|
|
|
foreach ( $data as $key => $value ) {
|
|
|
|
|
$template = str_replace( '{' . $key . '}', (string) $value, $template );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $template;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get template content.
|
|
|
|
|
*
|
|
|
|
|
* @param string $template_name Template name.
|
|
|
|
|
* @return string Template HTML.
|
|
|
|
|
*/
|
|
|
|
|
private static function get_template_content( string $template_name ): string {
|
|
|
|
|
// Built-in templates. Could be extended to load from files.
|
|
|
|
|
$templates = array(
|
|
|
|
|
'admin-new-booking' => self::template_admin_new_booking(),
|
|
|
|
|
'booking-confirmed' => self::template_booking_confirmed(),
|
|
|
|
|
'admin-booking-confirmed' => self::template_admin_booking_confirmed(),
|
|
|
|
|
'booking-cancelled' => self::template_booking_cancelled(),
|
|
|
|
|
'admin-booking-cancelled' => self::template_admin_booking_cancelled(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return $templates[ $template_name ] ?? '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Send HTML email.
|
|
|
|
|
*
|
|
|
|
|
* @param string $to Recipient email.
|
|
|
|
|
* @param string $subject Email subject.
|
|
|
|
|
* @param string $message HTML message.
|
|
|
|
|
* @return bool Whether email was sent.
|
|
|
|
|
*/
|
|
|
|
|
private static function send_email( string $to, string $subject, string $message ): bool {
|
|
|
|
|
$headers = array(
|
|
|
|
|
'Content-Type: text/html; charset=UTF-8',
|
|
|
|
|
'From: ' . get_bloginfo( 'name' ) . ' <' . get_option( 'admin_email' ) . '>',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Filter email recipients.
|
|
|
|
|
*
|
|
|
|
|
* @param string $to Recipient email.
|
|
|
|
|
* @param string $subject Email subject.
|
|
|
|
|
* @param string $message Email message.
|
|
|
|
|
*/
|
|
|
|
|
$to = apply_filters( 'wp_bnb_booking_email_recipients', $to, $subject, $message );
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Filter email subject.
|
|
|
|
|
*
|
|
|
|
|
* @param string $subject Email subject.
|
|
|
|
|
*/
|
|
|
|
|
$subject = apply_filters( 'wp_bnb_booking_email_subject', $subject );
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Filter email content.
|
|
|
|
|
*
|
|
|
|
|
* @param string $message Email message.
|
|
|
|
|
*/
|
|
|
|
|
$message = apply_filters( 'wp_bnb_booking_email_content', $message );
|
|
|
|
|
|
|
|
|
|
return wp_mail( $to, $subject, $message, $headers );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get base email styles.
|
|
|
|
|
*
|
|
|
|
|
* @return string CSS styles.
|
|
|
|
|
*/
|
|
|
|
|
private static function get_email_styles(): string {
|
|
|
|
|
return '
|
|
|
|
|
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-size: 14px; line-height: 1.6; color: #333; }
|
|
|
|
|
.email-container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
|
|
|
|
.email-header { background: #135e96; color: #fff; padding: 20px; text-align: center; }
|
|
|
|
|
.email-header h1 { margin: 0; font-size: 24px; }
|
|
|
|
|
.email-body { background: #fff; padding: 30px; border: 1px solid #ddd; }
|
|
|
|
|
.email-footer { padding: 20px; text-align: center; font-size: 12px; color: #666; }
|
|
|
|
|
.booking-details { background: #f9f9f9; padding: 15px; margin: 20px 0; border-left: 4px solid #135e96; }
|
|
|
|
|
.booking-details h3 { margin-top: 0; color: #135e96; }
|
|
|
|
|
.detail-row { margin: 8px 0; }
|
|
|
|
|
.detail-label { font-weight: 600; display: inline-block; min-width: 120px; }
|
|
|
|
|
.btn { display: inline-block; padding: 10px 20px; background: #135e96; color: #fff; text-decoration: none; border-radius: 4px; margin-top: 15px; }
|
|
|
|
|
.status-badge { display: inline-block; padding: 4px 10px; border-radius: 3px; font-size: 12px; font-weight: 600; text-transform: uppercase; }
|
|
|
|
|
.status-pending { background: #dba617; color: #fff; }
|
|
|
|
|
.status-confirmed { background: #00a32a; color: #fff; }
|
|
|
|
|
.status-cancelled { background: #d63638; color: #fff; }
|
|
|
|
|
';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Template: Admin new booking notification.
|
|
|
|
|
*
|
|
|
|
|
* @return string Template HTML.
|
|
|
|
|
*/
|
|
|
|
|
private static function template_admin_new_booking(): string {
|
|
|
|
|
$styles = self::get_email_styles();
|
|
|
|
|
|
|
|
|
|
return <<<HTML
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<style>{$styles}</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="email-container">
|
|
|
|
|
<div class="email-header">
|
|
|
|
|
<h1>New Booking Received</h1>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="email-body">
|
|
|
|
|
<p>A new booking has been created and is awaiting confirmation.</p>
|
|
|
|
|
|
|
|
|
|
<div class="booking-details">
|
|
|
|
|
<h3>Booking Details</h3>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Reference:</span> {booking_reference}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Status:</span> <span class="status-badge status-{status_raw}">{status}</span></div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Room:</span> {room_name}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Building:</span> {building_name}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Check-in:</span> {check_in_date}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Check-out:</span> {check_out_date}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Nights:</span> {nights}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Total:</span> {total_price}</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="booking-details">
|
|
|
|
|
<h3>Guest Information</h3>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Name:</span> {guest_name}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Email:</span> {guest_email}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Phone:</span> {guest_phone}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Adults:</span> {adults}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Children:</span> {children}</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<a href="{booking_url}" class="btn">View Booking</a>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="email-footer">
|
|
|
|
|
<p>This email was sent from {site_name}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|
HTML;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Template: Guest booking confirmed.
|
|
|
|
|
*
|
|
|
|
|
* @return string Template HTML.
|
|
|
|
|
*/
|
|
|
|
|
private static function template_booking_confirmed(): string {
|
|
|
|
|
$styles = self::get_email_styles();
|
|
|
|
|
|
|
|
|
|
return <<<HTML
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<style>{$styles}</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="email-container">
|
|
|
|
|
<div class="email-header">
|
|
|
|
|
<h1>Booking Confirmed</h1>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="email-body">
|
|
|
|
|
<p>Dear {guest_name},</p>
|
|
|
|
|
|
|
|
|
|
<p>Great news! Your booking has been confirmed. We look forward to welcoming you.</p>
|
|
|
|
|
|
|
|
|
|
<div class="booking-details">
|
|
|
|
|
<h3>Your Booking Details</h3>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Confirmation:</span> {booking_reference}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Room:</span> {room_name}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Location:</span> {building_name}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Check-in:</span> {check_in_date}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Check-out:</span> {check_out_date}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Duration:</span> {nights} nights</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Guests:</span> {adults} adults, {children} children</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Total:</span> <strong>{total_price}</strong></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<p>If you have any questions or need to make changes to your reservation, please contact us at {admin_email}.</p>
|
|
|
|
|
|
|
|
|
|
<p>Thank you for choosing us!</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="email-footer">
|
|
|
|
|
<p>{site_name}<br>{site_url}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|
HTML;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Template: Admin booking confirmed.
|
|
|
|
|
*
|
|
|
|
|
* @return string Template HTML.
|
|
|
|
|
*/
|
|
|
|
|
private static function template_admin_booking_confirmed(): string {
|
|
|
|
|
$styles = self::get_email_styles();
|
|
|
|
|
|
|
|
|
|
return <<<HTML
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<style>{$styles}</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="email-container">
|
|
|
|
|
<div class="email-header">
|
|
|
|
|
<h1>Booking Confirmed</h1>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="email-body">
|
|
|
|
|
<p>Booking {booking_reference} has been confirmed.</p>
|
|
|
|
|
|
|
|
|
|
<div class="booking-details">
|
|
|
|
|
<h3>Booking Summary</h3>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Guest:</span> {guest_name}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Room:</span> {room_name}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Dates:</span> {check_in_date} - {check_out_date}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Total:</span> {total_price}</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<a href="{booking_url}" class="btn">View Booking</a>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="email-footer">
|
|
|
|
|
<p>This email was sent from {site_name}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|
HTML;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Template: Guest booking cancelled.
|
|
|
|
|
*
|
|
|
|
|
* @return string Template HTML.
|
|
|
|
|
*/
|
|
|
|
|
private static function template_booking_cancelled(): string {
|
|
|
|
|
$styles = self::get_email_styles();
|
|
|
|
|
|
|
|
|
|
return <<<HTML
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<style>{$styles}</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="email-container">
|
|
|
|
|
<div class="email-header" style="background: #d63638;">
|
|
|
|
|
<h1>Booking Cancelled</h1>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="email-body">
|
|
|
|
|
<p>Dear {guest_name},</p>
|
|
|
|
|
|
|
|
|
|
<p>We're writing to confirm that your booking has been cancelled.</p>
|
|
|
|
|
|
|
|
|
|
<div class="booking-details">
|
|
|
|
|
<h3>Cancelled Booking</h3>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Reference:</span> {booking_reference}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Room:</span> {room_name}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Dates:</span> {check_in_date} - {check_out_date}</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<p>If you have any questions or would like to make a new reservation, please contact us at {admin_email}.</p>
|
|
|
|
|
|
|
|
|
|
<p>We hope to welcome you in the future.</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="email-footer">
|
|
|
|
|
<p>{site_name}<br>{site_url}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|
HTML;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Template: Admin booking cancelled.
|
|
|
|
|
*
|
|
|
|
|
* @return string Template HTML.
|
|
|
|
|
*/
|
|
|
|
|
private static function template_admin_booking_cancelled(): string {
|
|
|
|
|
$styles = self::get_email_styles();
|
|
|
|
|
|
|
|
|
|
return <<<HTML
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<style>{$styles}</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="email-container">
|
|
|
|
|
<div class="email-header" style="background: #d63638;">
|
|
|
|
|
<h1>Booking Cancelled</h1>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="email-body">
|
|
|
|
|
<p>Booking {booking_reference} has been cancelled.</p>
|
|
|
|
|
|
|
|
|
|
<div class="booking-details">
|
|
|
|
|
<h3>Cancelled Booking</h3>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Guest:</span> {guest_name}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Email:</span> {guest_email}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Room:</span> {room_name}</div>
|
|
|
|
|
<div class="detail-row"><span class="detail-label">Dates:</span> {check_in_date} - {check_out_date}</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<a href="{booking_url}" class="btn">View Booking</a>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="email-footer">
|
|
|
|
|
<p>This email was sent from {site_name}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|
HTML;
|
|
|
|
|
}
|
|
|
|
|
}
|