Plugin Directory

Changeset 3441012


Ignore:
Timestamp:
01/16/2026 01:17:25 PM (2 months ago)
Author:
creavi
Message:

Added booking reminder email feature

Location:
creavi-booking-service
Files:
29 added
5 edited

Legend:

Unmodified
Added
Removed
  • creavi-booking-service/trunk/creavi-booking-service.php

    r3439801 r3441012  
    44 * Description: A simple service booking system with popup UI.
    55 * Text Domain: creavi-booking-service
    6  * Version: 1.1.2
     6 * Version: 1.1.3
    77 * Author: Creavi
    88 * License: GPL2
     
    1414define('CREAVIBC_PLUGIN_URL', plugin_dir_url(__FILE__));
    1515define('CREAVIBC_PLUGIN_PATH', plugin_dir_path(__FILE__));
    16 define('CREAVIBC_VERSION', '1.1.1');
     16define('CREAVIBC_VERSION', '1.1.3');
    1717
    1818require_once CREAVIBC_PLUGIN_DIR . 'includes/cbs-gcal-remote.php';
     
    2626require_once CREAVIBC_PLUGIN_DIR . 'includes/gcal-freebusy.php';
    2727require_once CREAVIBC_PLUGIN_DIR . 'includes/ajax-handlers.php';
     28require_once CREAVIBC_PLUGIN_DIR . 'includes/reminders.php';
    2829
    2930
     
    99100    );
    100101}
     102
     103register_deactivation_hook(__FILE__, function () {
     104    $timestamp = wp_next_scheduled('creavibc_run_reminders');
     105    while ($timestamp) {
     106        wp_unschedule_event($timestamp, 'creavibc_run_reminders');
     107        $timestamp = wp_next_scheduled('creavibc_run_reminders');
     108    }
     109});
  • creavi-booking-service/trunk/includes/ajax-handlers.php

    r3439801 r3441012  
    2424    }
    2525});
    26 
    2726
    2827
     
    139138    }
    140139
    141 
    142 
    143     // >>> INSERT HERE (normalize timezone) ---------------------------------------
     140    // normalize timezone
    144141    if ($admin_tz === 'Europe/Kiev') {
    145142        $admin_tz = 'Europe/Kyiv';
     
    149146        $admin_tz = wp_timezone_string();
    150147    }
    151     // <<< END INSERT -------------------------------------------------------------
    152 
     148   
    153149
    154150    $start_dt_admin = new DateTime("$date $start_time", new DateTimeZone($admin_tz));
     
    232228    }
    233229
    234     // >>> REPLACE THIS BLOCK (fallback text)  ------------------------------------
     230   
    235231    $display_time_fallback = ($timezone_mode === 'locked') ? $display_time_admin : $display_time_user;
    236232
    237233    $fallback = "Booking for $service_title on $display_date at $display_time_fallback.\n"
    238234            . "Name: $name\nEmail: $user_email\n\n$custom_lines\nGoogle Calendar: $gcal_url";
    239     // <<< END REPLACE ------------------------------------------------------------
    240 
    241 
     235   
    242236   // $fallback = "Booking for $service_title on $display_date at $display_time.\nName: $name\nEmail: $user_email\n\n$custom_lines\nGoogle Calendar: $gcal_url";
    243237
     
    255249    // translators: %s: Service title
    256250    $user_subject  = sprintf(__('Your Booking: %s', 'creavi-booking-service'), $service_title);
    257 
    258     //$admin_email = 'juls@creavi.dk';
    259    // -> wp_mail($admin_email, $admin_subject, $final_admin_tpl, '', [$tmp_file]);
    260    // -> wp_mail($user_email, $user_subject, $final_user_tpl, '', [$tmp_file]);
    261 
    262 
    263    // =====================================================
     251   
     252
     253    // =====================================================
    264254    // MAIL: headers + logging + safe user send (replace here)
    265255    // =====================================================
     
    318308        ]);
    319309    }
    320 
    321 
    322310   
    323311    wp_delete_file($tmp_file);
     
    326314add_action('wp_ajax_creavibc_get_booked_slots', 'creavibc_get_booked_slots');
    327315add_action('wp_ajax_nopriv_creavibc_get_booked_slots', 'creavibc_get_booked_slots');
    328 /*
    329 function creavibc_get_booked_slots() {
    330     $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    331     if (!wp_verify_nonce($nonce, 'creavibc_booking_nonce')) {
    332         wp_send_json_error(['message' => __('Security check failed.', 'creavi-booking-service')]);
    333     }
    334 
    335     $date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : '';
    336     $service_id = isset($_POST['service_id']) ? intval(wp_unslash($_POST['service_id'])) : 0;
    337 
    338     if (!$date || !$service_id) {
    339         wp_send_json_error(['message' => __('Missing required fields.', 'creavi-booking-service')]);
    340     }
    341 
    342     $args = [
    343         'post_type'  => 'creavibc_booking',
    344         'post_status'=> 'publish',
    345         'meta_query' => [
    346             [
    347                 'key'   => '_creavibc_booking_date',
    348                 'value' => $date,
    349             ],
    350             [
    351                 'key'   => '_creavibc_booking_service_id',
    352                 'value' => $service_id,
    353             ]
    354         ],
    355         'fields' => 'ids',
    356         'posts_per_page' => -1,
    357     ];
    358 
    359     $bookings = get_posts($args);
    360     $booked_times = [];
    361 
    362     foreach ($bookings as $booking_id) {
    363         $time = get_post_meta($booking_id, '_creavibc_booking_time', true);
    364         if ($time) {
    365             $booked_times[] = $time;
    366         }
    367     }
    368 
    369     wp_send_json_success(['booked_slots' => $booked_times]);
    370 }*/
     316
    371317
    372318
     
    560506
    561507
    562 
    563 
    564508/**
    565509 * Push a booking to Google Calendar using the connector.
  • creavi-booking-service/trunk/includes/meta-boxes.php

    r3435778 r3441012  
    565565    echo '<p class="description">Available tags: {name}, {email}, {date}, {time}, {service}</p>';   
    566566
     567    // ---------------------------
     568    // Reminder email (per service)
     569    // ---------------------------
     570   // Reminder email (per service)
     571    $reminder_enabled = (bool) get_post_meta( $post->ID, '_creavibc_reminder_enabled', true );
     572
     573    $reminder_offset = (int) get_post_meta( $post->ID, '_creavibc_reminder_offset_minutes', true );
     574    if ( $reminder_offset <= 0 ) {
     575        $reminder_offset = 1440; // Default: 1 day
     576    }
     577
     578    $reminder_subject = get_post_meta( $post->ID, '_creavibc_email_reminder_subject', true );
     579    if ( empty( $reminder_subject ) ) {
     580        $reminder_subject = 'Reminder: {service} on {date} at {time}';
     581    }
     582
     583    $reminder_tpl = get_post_meta( $post->ID, '_creavibc_email_reminder_template', true );
     584    if ( empty( $reminder_tpl ) ) {
     585        $reminder_tpl = "Hi {name},\n\nJust a friendly reminder about your upcoming appointment:\n\nService: {service}\nDate: {date}\nTime: {time}\n\nSee you soon!";
     586    }
     587
     588    $reminder_options = array(
     589        // Minutes
     590        10   => __( '10 minutes before', 'creavi-booking-service' ),
     591        20   => __( '20 minutes before', 'creavi-booking-service' ),
     592        30   => __( '30 minutes before', 'creavi-booking-service' ),
     593        40   => __( '40 minutes before', 'creavi-booking-service' ),
     594        50   => __( '50 minutes before', 'creavi-booking-service' ),
     595
     596        // Hours
     597        60   => __( '1 hour before', 'creavi-booking-service' ),
     598        120  => __( '2 hours before', 'creavi-booking-service' ),
     599        180  => __( '3 hours before', 'creavi-booking-service' ),
     600        240  => __( '4 hours before', 'creavi-booking-service' ),
     601        300  => __( '5 hours before', 'creavi-booking-service' ),
     602        360  => __( '6 hours before', 'creavi-booking-service' ),
     603        420  => __( '7 hours before', 'creavi-booking-service' ),
     604        480  => __( '8 hours before', 'creavi-booking-service' ),
     605        540  => __( '9 hours before', 'creavi-booking-service' ),
     606        600  => __( '10 hours before', 'creavi-booking-service' ),
     607        660  => __( '11 hours before', 'creavi-booking-service' ),
     608        720  => __( '12 hours before', 'creavi-booking-service' ),
     609
     610        // Day
     611        1440 => __( '1 day before', 'creavi-booking-service' ),
     612    );
     613
     614
     615    echo '<hr><h4 class="creavibc-subsection">' . esc_html__( 'Reminder Email', 'creavi-booking-service' ) . '</h4>';
     616
     617    echo '<label style="display:block; margin:0 0 10px;">';
     618    echo '<input type="checkbox" name="creavibc_reminder_enabled" value="1" ' . checked( $reminder_enabled, true, false ) . '> ';
     619    echo '<strong>' . esc_html__( 'Enable reminder email (user)', 'creavi-booking-service' ) . '</strong><br>';
     620    echo '<span style="color:#666;">' . esc_html__( 'Sends an automatic reminder to the customer before the appointment.', 'creavi-booking-service' ) . '</span>';
     621    echo '</label>';
     622
     623    echo '<p style="margin:0 0 10px;">';
     624    echo '<label for="creavibc_reminder_offset_minutes"><strong>' . esc_html__( 'Send reminder', 'creavi-booking-service' ) . '</strong></label><br>';
     625    echo '<select id="creavibc_reminder_offset_minutes" name="creavibc_reminder_offset_minutes">';
     626    foreach ( $reminder_options as $minutes => $label ) {
     627        echo '<option value="' . esc_attr( $minutes ) . '" ' . selected( $reminder_offset, $minutes, false ) . '>' . esc_html( $label ) . '</option>';
     628    }
     629    echo '</select>';
     630    echo '</p>';
     631
     632    echo '<p><label for="creavibc_email_reminder_subject"><strong>' . esc_html__( 'Reminder Email Subject', 'creavi-booking-service' ) . '</strong></label><br>';
     633    echo '<input type="text" id="creavibc_email_reminder_subject" name="creavibc_email_reminder_subject" value="' . esc_attr( $reminder_subject ) . '" style="width:100%"></p>';
     634
     635    echo '<p><label for="creavibc_email_reminder_template"><strong>' . esc_html__( 'Reminder Email Template', 'creavi-booking-service' ) . '</strong></label><br>';
     636    echo '<textarea name="creavibc_email_reminder_template" id="creavibc_email_reminder_template" rows="6" style="width:100%;">' . esc_textarea( $reminder_tpl ) . '</textarea></p>';
     637
     638    echo '<p class="description">';
     639    echo esc_html__( 'Available tags:', 'creavi-booking-service' ) . ' ';
     640    echo '{name}, {email}, {date}, {time}, {service}';
     641    echo '</p>';
     642
     643
     644
    567645}
    568646
  • creavi-booking-service/trunk/includes/save-service.php

    r3435778 r3441012  
    156156        update_post_meta($post_id, '_creavibc_button_padding_horizontal', sanitize_text_field(wp_unslash($_POST['creavibc_button_padding_horizontal'] ?? '')));
    157157
     158        /* --- Reminder Email (per-service) --- */
     159        update_post_meta(
     160            $post_id,
     161            '_creavibc_reminder_enabled',
     162            isset($_POST['creavibc_reminder_enabled']) ? '1' : '0'
     163        );
     164
     165        if (isset($_POST['creavibc_reminder_offset_minutes'])) {
     166            $offset = absint($_POST['creavibc_reminder_offset_minutes']);
     167            // Allow only safe presets (prevents random values + keeps UI consistent)
     168            $allowed_offsets = array(
     169                10, 20, 30, 40, 50,
     170                60, 120, 180, 240, 300, 360,
     171                420, 480, 540, 600, 660, 720,
     172                1440,
     173            );
     174
     175            if (!in_array($offset, $allowed_offsets, true)) {
     176                $offset = 1440;
     177            }
     178            update_post_meta($post_id, '_creavibc_reminder_offset_minutes', $offset);
     179        }
     180
     181        if (isset($_POST['creavibc_email_reminder_subject'])) {
     182            update_post_meta(
     183                $post_id,
     184                '_creavibc_email_reminder_subject',
     185                sanitize_text_field(wp_unslash($_POST['creavibc_email_reminder_subject']))
     186            );
     187        }
     188
     189        if (isset($_POST['creavibc_email_reminder_template'])) {
     190            update_post_meta(
     191                $post_id,
     192                '_creavibc_email_reminder_template',
     193                sanitize_textarea_field(wp_unslash($_POST['creavibc_email_reminder_template']))
     194            );
     195        }
     196        /* --- /Reminder Email --- */
    158197
    159198
     
    176215        }
    177216
    178         // 🔹 NEW: Save per-service target calendar ID
     217        // Save per-service target calendar ID
    179218        if (isset($_POST['creavibc_gcal_calendar_id'])) {
    180219            $cal = sanitize_text_field(wp_unslash($_POST['creavibc_gcal_calendar_id']));
  • creavi-booking-service/trunk/readme.txt

    r3439801 r3441012  
    55Tested up to: 6.8 
    66Requires PHP: 7.4 
    7 Stable tag: 1.1.2
     7Stable tag: 1.1.3
    88License: GPLv2 or later 
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    8787== Changelog ==
    8888
     89= 1.1.3 =
     90* Added automated reminder emails for bookings (per service).
     91* New service option to enable/disable reminder emails.
     92* New reminder timing settings (minutes, hours, or 1 day before the appointment).
     93* Added customizable reminder email subject and message templates.
     94
    8995= 1.1.2 =
    9096* Fixed an issue allowing bookings in the past on the current day.
Note: See TracChangeset for help on using the changeset viewer.