log = new Moceansms_WooCoommerce_Logger();
$this->option_id = "moceansms_{$this::$plugin_identifier}";
$this->plugin_name = 'BookIt';
$this->plugin_medium = 'wp_' . str_replace( ' ', '_', strtolower($this->plugin_name));
$this->hook_action = "moceansms_send_reminder_{$this::$plugin_identifier}";
}
public function register()
{
add_action( 'bookit_appointment_status_changed', array($this, 'send_sms_on_appointment_status_changed'), 10, 1 );
add_action( $this->hook_action, array($this, 'send_sms_reminder'), 10, 2);
}
public function get_option_id()
{
return $this->option_id;
}
public static function plugin_activated()
{
if( ! is_plugin_active(sprintf("%s/%s.php", self::$plugin_identifier, self::$plugin_identifier))) {
return false;
}
try {
require_once BOOKIT_CLASSES_PATH . "database/Appointments.php";
return true;
} catch (Exception $e) {
$log = new Moceansms_WooCoommerce_Logger();
$log->add("360MessengerWhatsApp", "Failed to import database/Appointments.php from BookIt");
$log->add("360MessengerWhatsApp", "Aborting...");
$log->add("360MessengerWhatsApp", print_r($e, true));
return false;
}
}
public function get_setting_section_data()
{
return array(
'id' => $this->get_option_id(),
'title' => __( $this->plugin_name, MOCEANSMS_TEXT_DOMAIN ),
);
}
public function get_setting_field_data()
{
$setting_fields = array(
$this->get_enable_notification_fields(),
//$this->get_send_from_fields(),
$this->get_send_on_fields(),
);
foreach($this->get_reminder_fields() as $reminder) {
$setting_fields[] = $reminder;
}
foreach($this->get_sms_reminder_template_fields() as $sms_reminder) {
$setting_fields[] = $sms_reminder;
}
foreach($this->get_sms_template_fields() as $sms_templates) {
$setting_fields[] = $sms_templates;
}
return $setting_fields;
}
private function get_enable_notification_fields() {
return array(
'name' => 'moceansms_automation_enable_notification',
'label' => __( 'Enable WhatsApp notifications', MOCEANSMS_TEXT_DOMAIN ),
'desc' => ' ' . __( 'Enable', MOCEANSMS_TEXT_DOMAIN ),
'type' => 'checkbox',
'default' => 'off'
);
}
private function get_send_from_fields() {
return array(
'name' => 'moceansms_automation_send_from',
'label' => __( 'Send from', MOCEANSMS_TEXT_DOMAIN ),
'desc' => __( 'Sender of the WhatsApp when a message is received at a mobile phone', MOCEANSMS_TEXT_DOMAIN ),
'type' => 'text',
);
}
private function get_send_on_fields() {
return array(
'name' => 'moceansms_automation_send_on',
'label' => __( 'Send notification on', MOCEANSMS_TEXT_DOMAIN ),
'desc' => __( 'Choose when to send a WhatsApp notification message to your customer', MOCEANSMS_TEXT_DOMAIN ),
'type' => 'multicheck',
'options' => array(
'appointment_pending' => 'Appointment pending',
'appointment_approved' => 'Appointment approved',
'appointment_cancelled' => 'Appointment cancelled',
)
);
}
private function get_sms_template_fields() {
return array(
array(
'name' => 'moceansms_automation_sms_template_appointment_pending',
'label' => __( 'Appointment pending WhatsApp message', MOCEANSMS_TEXT_DOMAIN ),
'desc' => sprintf('Customize your WhatsApp with ', $this->get_option_id() ),
'type' => 'textarea',
'rows' => '8',
'cols' => '500',
'css' => 'min-width:350px;',
'default' => __( 'Greetings [customer_name], your appointment for [service_name] on [appointment_day] is [appointment_status]', MOCEANSMS_TEXT_DOMAIN )
),
array(
'name' => 'moceansms_automation_sms_template_appointment_approved',
'label' => __( 'Appointment approved WhatsApp message', MOCEANSMS_TEXT_DOMAIN ),
'desc' => sprintf('Customize your WhatsApp with ', $this->get_option_id() ),
'type' => 'textarea',
'rows' => '8',
'cols' => '500',
'css' => 'min-width:350px;',
'default' => __( 'Greetings [customer_name], your appointment for [service_name] on [appointment_day] is [appointment_status]', MOCEANSMS_TEXT_DOMAIN )
),
array(
'name' => 'moceansms_automation_sms_template_appointment_cancelled',
'label' => __( 'Appointment cancelled WhatsApp message', MOCEANSMS_TEXT_DOMAIN ),
'desc' => sprintf('Customize your WhatsApp with ', $this->get_option_id() ),
'type' => 'textarea',
'rows' => '8',
'cols' => '500',
'css' => 'min-width:350px;',
'default' => __( 'Greetings [customer_name], your appointment for [service_name] on [appointment_day] is [appointment_status]', MOCEANSMS_TEXT_DOMAIN )
),
);
}
private function get_reminder_fields() {
return array(
array(
'name' => 'moceansms_automation_reminder',
'label' => __( 'Send reminder to customer reservation', MOCEANSMS_TEXT_DOMAIN ),
'desc' => __( '', MOCEANSMS_TEXT_DOMAIN ),
'type' => 'multicheck',
'options' => array(
'rem_1' => '15 minutes before reservation',
'rem_2' => '30 minutes before reservation',
'rem_3' => '60 minutes before reservation',
'custom' => 'Custom time before reservation',
)
),
array(
'name' => 'moceansms_automation_reminder_custom_time',
'label' => __( '', MOCEANSMS_TEXT_DOMAIN ),
'desc' => __( 'Enter the custom time you want to remind your customer before reservation in (minutes)
Choose when to send a WhatsApp reminder message to your customer
Please set your timezone in settings
You must setup cronjob here ', MOCEANSMS_TEXT_DOMAIN ),
'type' => 'number',
),
);
}
private function get_sms_reminder_template_fields() {
return array(
array(
'name' => 'moceansms_automation_sms_template_rem_1',
'label' => __( '15 minutes reminder WhatsApp message', MOCEANSMS_TEXT_DOMAIN ),
'desc' => sprintf('Customize your WhatsApp with ', $this->get_option_id() ),
'type' => 'textarea',
'rows' => '8',
'cols' => '500',
'css' => 'min-width:350px;',
'default' => __( 'Greetings [customer_name], your appointment for [service_name] on [appointment_day] is [appointment_status].', MOCEANSMS_TEXT_DOMAIN )
),
array(
'name' => 'moceansms_automation_sms_template_rem_2',
'label' => __( '30 minutes reminder WhatsApp message', MOCEANSMS_TEXT_DOMAIN ),
'desc' => sprintf('Customize your WhatsApp with ', $this->get_option_id() ),
'type' => 'textarea',
'rows' => '8',
'cols' => '500',
'css' => 'min-width:350px;',
'default' => __( 'Greetings [customer_name], your appointment for [service_name] on [appointment_day] is [appointment_status].', MOCEANSMS_TEXT_DOMAIN )
),
array(
'name' => 'moceansms_automation_sms_template_rem_3',
'label' => __( '60 minutes reminder WhatsApp message', MOCEANSMS_TEXT_DOMAIN ),
'desc' => sprintf('Customize your WhatsApp with ', $this->get_option_id() ),
'type' => 'textarea',
'rows' => '8',
'cols' => '500',
'css' => 'min-width:350px;',
'default' => __( 'Greetings [customer_name], your appointment for [service_name] on [appointment_day] is [appointment_status].', MOCEANSMS_TEXT_DOMAIN )
),
array(
'name' => 'moceansms_automation_sms_template_custom',
'label' => __( 'Custom time reminder WhatsApp Message', MOCEANSMS_TEXT_DOMAIN ),
'desc' => sprintf('Customize your WhatsApp with ', $this->get_option_id() ),
'type' => 'textarea',
'rows' => '8',
'cols' => '500',
'css' => 'min-width:350px;',
'default' => __( 'Greetings [customer_name], your appointment for [service_name] on [appointment_day] is [appointment_status]. - custom', MOCEANSMS_TEXT_DOMAIN )
),
);
}
private function schedule_reminders($app_id, $status) {
$send_sms_reminder_flag = true;
$settings = $this->get_plugin_settings();
$appointment = \Bookit\Classes\Database\Appointments::get_full_appointment_by_id($app_id);
// do our reminder stuff
$as_group = "{$this::$plugin_identifier}_{$appointment->id}";
$format = get_option('date_format');
// UTC booking date
$appointment_date = DateTime::createFromFormat('U', $appointment->start_time)->format('Y-m-d H:i:s');
// Direct convert to local timezone
$local_appointment_date = DateTime::createFromFormat('Y-m-d H:i:s', $appointment_date, wp_timezone());
$reminder_booking_date_15 = DateTime::createFromFormat('Y-m-d H:i:s', $appointment_date, wp_timezone());
$reminder_booking_date_30 = DateTime::createFromFormat('Y-m-d H:i:s', $appointment_date, wp_timezone());
$reminder_booking_date_60 = DateTime::createFromFormat('Y-m-d H:i:s', $appointment_date, wp_timezone());
// current local time
$current_time = date_i18n('Y-m-d H:i:s O');
$now_date = DateTime::createFromFormat('Y-m-d H:i:s O', $current_time, wp_timezone())->format($format);
$now_timestamp = DateTime::createFromFormat('Y-m-d H:i:s O', $current_time, wp_timezone())->getTimestamp();
// $now_timestamp = strtotime("+1 minute", $now_timestamp);
$this->log->add("360MessengerWhatsApp", "Booking date: {$appointment_date}");
$this->log->add("360MessengerWhatsApp", "Current Local Date: {$now_date}");
$this->log->add("360MessengerWhatsApp", "Current Local Timestamp: {$now_timestamp}");
$this->log->add("360MessengerWhatsApp", "Booking date to Local time: {$local_appointment_date->format($format)}");
$custom_reminder_time = $settings['moceansms_automation_reminder_custom_time'];
if(!ctype_digit($custom_reminder_time)) {
$this->log->add("360MessengerWhatsApp", "reminder time (in minutes) is not digit");
$send_sms_reminder_flag = false;
}
$reminder_date_15 = $reminder_booking_date_15->modify("-15 minutes")->getTimestamp();
$reminder_date_30 = $reminder_booking_date_30->modify("-30 minutes")->getTimestamp();
$reminder_date_60 = $reminder_booking_date_60->modify("-60 minutes")->getTimestamp();
$this->log->add("360MessengerWhatsApp", "15 mins Reminder timestamp: {$reminder_date_15}");
$this->log->add("360MessengerWhatsApp", "30 mins Reminder timestamp: {$reminder_date_30}");
$this->log->add("360MessengerWhatsApp", "60 mins Reminder timestamp: {$reminder_date_60}");
$this->log->add("360MessengerWhatsApp", "Unscheduling all WhatsApp reminders for Group: {$as_group}");
as_unschedule_all_actions('', array(), $as_group);
$action_id_15 = as_schedule_single_action($reminder_date_15, $this->hook_action, array($appointment, 'rem_1'), $as_group );
$action_id_30 = as_schedule_single_action($reminder_date_30, $this->hook_action, array($appointment, 'rem_2'), $as_group );
$action_id_60 = as_schedule_single_action($reminder_date_60, $this->hook_action, array($appointment, 'rem_3'), $as_group );
$this->log->add("360MessengerWhatsApp", "Send WhatsApp Reminder scheduled, action_id_15 = {$action_id_15}");
$this->log->add("360MessengerWhatsApp", "Send WhatsApp Reminder scheduled, action_id_30 = {$action_id_30}");
$this->log->add("360MessengerWhatsApp", "Send WhatsApp Reminder scheduled, action_id_60 = {$action_id_60}");
if($send_sms_reminder_flag) {
$reminder_date_custom = $local_appointment_date->modify("-{$custom_reminder_time} minutes")->getTimestamp();
$this->log->add("360MessengerWhatsApp", "Custom Reminder timestamp: {$reminder_date_custom}");
$action_id_custom = as_schedule_single_action($reminder_date_custom, $this->hook_action, array($appointment, 'custom'), $as_group );
$this->log->add("360MessengerWhatsApp", "Send WhatsApp Reminder scheduled, action_id_custom = {$action_id_custom}");
}
}
public function send_sms_reminder($appointment, $status)
{
$appointment = (object) $appointment;
$this->log->add("360MessengerWhatsApp", "Appointment status: {$appointment->status}");
$this->log->add("360MessengerWhatsApp", "Status: {$status}");
if($appointment->status !== 'approved') {
$this->log->add("360MessengerWhatsApp", "Appointment status is not approved, status: {$appointment->status}");
$this->log->add("360MessengerWhatsApp", "not sending reminder.");
return;
}
$appointment_date = DateTime::createFromFormat('U', $appointment->start_time)->format('Y-m-d H:i:s');
$local_appointment_date = DateTime::createFromFormat('Y-m-d H:i:s', $appointment_date, wp_timezone());
// Direct convert to local timezone
$local_appointment_timestamp = $local_appointment_date->getTimestamp();
$now_timestamp = current_datetime()->getTimestamp();
$this->log->add("360MessengerWhatsApp", "appointment timestamp: {$local_appointment_timestamp}");
$this->log->add("360MessengerWhatsApp", "now timestamp: {$now_timestamp}");
// membership already expired
if($now_timestamp >= $local_appointment_timestamp) {
$this->log->add("360MessengerWhatsApp", "Appointment date is in the past");
return;
}
$settings = $this->get_plugin_settings();
$enable_notifications = $settings['moceansms_automation_enable_notification'];
$reminder = $settings['moceansms_automation_reminder'];
$this->log->add("360MessengerWhatsApp", "Successfully retrieved plugin settings");
if($enable_notifications === "on"){
$this->log->add("360MessengerWhatsApp", "enable_notifications: {$enable_notifications}");
if(!empty($reminder) && is_array($reminder)) {
if(array_key_exists($status, $reminder)) {
$this->log->add("360MessengerWhatsApp", "Sending reminder now");
$this->send_customer_notification($appointment, $status);
}
}
}
}
public function get_plugin_settings($with_identifier = false)
{
$settings = array(
"moceansms_automation_enable_notification" => moceansms_get_options("moceansms_automation_enable_notification", $this->get_option_id()),
"moceansms_send_from" => moceansms_get_options('moceansms_automation_send_from', $this->get_option_id()),
"moceansms_automation_send_on" => moceansms_get_options("moceansms_automation_send_on", $this->get_option_id()),
"moceansms_automation_reminder" => moceansms_get_options("moceansms_automation_reminder", $this->get_option_id()),
"moceansms_automation_reminder_custom_time" => moceansms_get_options("moceansms_automation_reminder_custom_time", $this->get_option_id()),
"moceansms_automation_sms_template_rem_1" => moceansms_get_options("moceansms_automation_sms_template_rem_1", $this->get_option_id()),
"moceansms_automation_sms_template_rem_2" => moceansms_get_options("moceansms_automation_sms_template_rem_2", $this->get_option_id()),
"moceansms_automation_sms_template_rem_3" => moceansms_get_options("moceansms_automation_sms_template_rem_3", $this->get_option_id()),
"moceansms_automation_sms_template_custom" => moceansms_get_options("moceansms_automation_sms_template_custom", $this->get_option_id()),
"moceansms_automation_sms_template_appointment_pending" => moceansms_get_options("moceansms_automation_sms_template_appointment_pending", $this->get_option_id()),
"moceansms_automation_sms_template_appointment_approved" => moceansms_get_options("moceansms_automation_sms_template_appointment_approved", $this->get_option_id()),
"moceansms_automation_sms_template_appointment_cancelled" => moceansms_get_options("moceansms_automation_sms_template_appointment_cancelled", $this->get_option_id()),
);
if ($with_identifier) {
return array(
self::$plugin_identifier => $settings,
);
}
return $settings;
}
public function get_keywords_field()
{
return array(
'appointment' => array(
'appointment_id',
'appointment_day',
'appointment_price',
'appointment_total_price',
'appointment_status',
'appointment_start_time',
'appointment_end_time',
),
'service' => array(
'service_name',
),
'staff' => array(
'staff_email',
'staff_id',
'staff_phone',
'staff_name',
),
'customer' => array(
'customer_name',
'customer_email',
'customer_phone',
),
'payment' => array(
'payment_method',
'payment_status',
),
'moceansms' => array(
'reminder_custom_time',
),
);
}
public function send_sms_on_appointment_status_changed($app_id)
{
$appointment = \Bookit\Classes\Database\Appointments::get_full_appointment_by_id($app_id);
$status_choices = ['pending', 'approved', 'cancelled'];
if(!in_array($appointment->status, $status_choices)) { return; }
$status = "appointment_{$appointment->status}";
if($appointment->status == 'approved') {
$this->log->add("360MessengerWhatsApp", "appointment status: {$appointment->status}");
$this->log->add("360MessengerWhatsApp", "Scheduling reminder");
$this->schedule_reminders($app_id, $status);
}
$this->send_sms_on($appointment, $status);
}
public function send_sms_on($appointment, $status)
{
$plugin_settings = $this->get_plugin_settings();
$enable_notifications = $plugin_settings['moceansms_automation_enable_notification'];
$send_on = $plugin_settings['moceansms_automation_send_on'];
if($enable_notifications === "on"){
if(!empty($send_on) && is_array($send_on)) {
if(array_key_exists($status, $send_on)) {
$this->send_customer_notification($appointment, $status);
}
}
}
return;
}
public function send_customer_notification($appointment, $status)
{
$settings = $this->get_plugin_settings();
$sms_from = $settings['moceansms_automation_send_from'];
$phone_no = $appointment->customer_phone;
// get message template from status
$msg_template = $settings["moceansms_automation_sms_template_{$status}"];
$message = $this->replace_keywords_with_value($appointment, $msg_template, $status);
$validated_number = MoceanSMS_SendSMS_Sms::get_formatted_number($phone_no);
MoceanSMS_SendSMS_Sms::send_sms($sms_from, $validated_number, $message, $this->plugin_medium);
}
/*
returns the message with keywords replaced to original value it points to
eg: [name] => 'customer name here'
*/
protected function replace_keywords_with_value($appointment, $message, $status)
{
// use regex to match all [stuff_inside]
// return the message
preg_match_all('/\[(.*?)\]/', $message, $keywords);
if($keywords) {
foreach($keywords[1] as $keyword) {
$keyword_value = $this->keyword_mapper($appointment, $keyword);
if( !empty($keyword_value) ) {
$message = str_replace("[{$keyword}]", $keyword_value, $message);
}
else if($keyword == 'reminder_custom_time') {
$settings = $this->get_plugin_settings();
$reminder_time = $settings['moceansms_automation_reminder_custom_time'];
$message = str_replace("[{$keyword}]", $this->seconds_to_days($reminder_time), $message);
}
else {
$message = str_replace("[{$keyword}]", "", $message);
}
}
}
return $message;
}
protected function keyword_mapper($appointment, $keyword) {
$keyword_mappers = array(
'appointment_id' => $appointment->id,
'appointment_day' => date( get_option('date_format'), $appointment->date_timestamp ),
'appointment_price' => $appointment->price,
'appointment_total_price' => bookit_price($appointment->price),
'appointment_status' => $appointment->status,
'appointment_start_time' => date( get_option('time_format'), $appointment->start_time ),
'appointment_end_time' => date( get_option('time_format'), $appointment->end_time ),
'service_name' => $appointment->service_name,
'staff_id' => $appointment->staff_id,
'staff_name' => $appointment->staff_name,
'staff_email' => $appointment->staff_email,
'staff_phone' => $appointment->staff_phone,
'customer_name' => $appointment->customer_name,
'customer_email' => $appointment->customer_email,
'customer_phone' => $appointment->customer_phone,
'payment_method' => $appointment->payment_method,
'payment_status' => $appointment->payment_status,
);
if(!array_key_exists($keyword, $keyword_mappers)) { return ''; }
return $keyword_mappers[$keyword];
}
private function seconds_to_days($seconds) {
if(!ctype_digit($seconds)) {
$this->log->add("360MessengerWhatsApp", 'seconds_to_days: $seconds is not a valid digit');
return '';
}
$ret = "";
$days = intval(intval($seconds) / (3600*24));
if($days> 0)
{
$ret .= "{$days}";
}
return $ret;
}
}