| 1 |
<?php |
| 2 |
/* @wordpress-plugin |
| 3 |
* Plugin Name: Spoki - Chat Buttons and WooCommerce Notifications |
| 4 |
* Description: Integrate WhatsApp on your Business! Use Spoki to recover abandoned carts, add chat buttons and send order status notifications via WhatsApp. |
| 5 |
* Version: 2.8.3 |
| 6 |
* Author: Reddoak Srl |
| 7 |
* Author URI: https://reddoak.com |
| 8 |
* Text Domain: spoki |
| 9 |
* Domain Path: /languages |
| 10 |
* License: GPLv2 |
| 11 |
*/ |
| 12 |
|
| 13 |
define('SPOKI_PLUGIN_FILE', __FILE__); |
| 14 |
define('SPOKI_BASE', plugin_basename(SPOKI_PLUGIN_FILE)); |
| 15 |
define('SPOKI_DIR', plugin_dir_path(SPOKI_PLUGIN_FILE)); |
| 16 |
define('SPOKI_URL', plugins_url('/', SPOKI_PLUGIN_FILE)); |
| 17 |
define('SPOKI_SETTING_TABLE', 'spoki_setting'); |
| 18 |
define('SPOKI_ABANDONMENT_TABLE', 'spoki_abandonment'); |
| 19 |
|
| 20 |
include_once SPOKI_DIR . 'includes/constants.php'; |
| 21 |
include_once SPOKI_DIR . 'includes/spoki-functions.php'; |
| 22 |
include_once SPOKI_DIR . 'modules/abandoned-carts/spoki-abandoned-carts.php'; |
| 23 |
|
| 24 |
add_filter('cron_schedules', 'add_cron_interval'); |
| 25 |
function add_cron_interval($schedules) |
| 26 |
{ |
| 27 |
$schedules['every_day'] = array( |
| 28 |
'interval' => 86400, |
| 29 |
'display' => esc_html__('Every day'),); |
| 30 |
return $schedules; |
| 31 |
} |
| 32 |
|
| 33 |
add_action('plugins_loaded', function () { |
| 34 |
/** Init Spoki */ |
| 35 |
Spoki(); |
| 36 |
}, 9); |
| 37 |
|
| 38 |
|
| 39 |
function Spoki() |
| 40 |
{ |
| 41 |
return WpSpoki::instance(); |
| 42 |
} |
| 43 |
|
| 44 |
final class WpSpoki |
| 45 |
{ |
| 46 |
protected static $_instance = null; |
| 47 |
public $version = ''; |
| 48 |
private $langs = ''; |
| 49 |
public $shop = []; |
| 50 |
|
| 51 |
private $api_plan = SPOKI_BASE_API . "plan/"; |
| 52 |
private $api_status = SPOKI_BASE_API . "status/"; |
| 53 |
private $api_enable_flex = SPOKI_BASE_API . "enable/"; |
| 54 |
private $api_account = SPOKI_BASE_API . "account/"; |
| 55 |
|
| 56 |
public static function instance() |
| 57 |
{ |
| 58 |
if (is_null(self::$_instance)) { |
| 59 |
self::$_instance = new self(); |
| 60 |
} |
| 61 |
return self::$_instance; |
| 62 |
} |
| 63 |
|
| 64 |
private function __construct() |
| 65 |
{ |
| 66 |
$data = get_file_data(__FILE__, array('ver' => 'Version', 'langs' => 'Domain Path')); |
| 67 |
$this->version = $data['ver']; |
| 68 |
$this->langs = $data['langs']; |
| 69 |
$this->options = get_option(SPOKI_OPTIONS); |
| 70 |
|
| 71 |
$billing_data = isset($this->options['billing_data']) ? $this->options['billing_data'] : []; |
| 72 |
$has_fixed_support_button = isset($this->options['buttons']['fixed_support_button_check']) && $this->options['buttons']['fixed_support_button_check'] == 1; |
| 73 |
$has_product_item_listing_button = isset($this->options['woocommerce']['product_item_listing_button_check']) && $this->options['woocommerce']['product_item_listing_button_check'] == 1; |
| 74 |
$has_cart_button = isset($this->options['woocommerce']['cart_button_check']) && $this->options['woocommerce']['cart_button_check'] == 1; |
| 75 |
$has_single_product_button = isset($this->options['woocommerce']['single_product_button_check']) && $this->options['woocommerce']['single_product_button_check'] == 1; |
| 76 |
$has_abandoned_carts = isset($this->options['abandoned_carts']['enable_tracking']) && $this->options['abandoned_carts']['enable_tracking'] == 1; |
| 77 |
$has_order_updated_notification = (isset($this->options['woocommerce']['order_updated']) && $this->options['woocommerce']['order_updated'] == 1); |
| 78 |
$has_order_created_notification = (isset($this->options['woocommerce']['order_created']) && $this->options['woocommerce']['order_created'] == 1); |
| 79 |
$has_order_deleted_notification = (isset($this->options['woocommerce']['order_deleted']) && $this->options['woocommerce']['order_deleted'] == 1); |
| 80 |
$has_order_note_added_notification = (isset($this->options['woocommerce']['order_note_added']) && $this->options['woocommerce']['order_note_added'] == 1); |
| 81 |
$has_leave_review_notification = (isset($this->options['woocommerce']['leave_review']) && $this->options['woocommerce']['leave_review'] == 1); |
| 82 |
$has_notifications = ( |
| 83 |
$has_order_updated_notification || |
| 84 |
$has_order_created_notification || |
| 85 |
$has_order_deleted_notification || |
| 86 |
$has_order_note_added_notification || |
| 87 |
$has_leave_review_notification |
| 88 |
); |
| 89 |
$has_order_created_to_seller_notification = (isset($this->options['woocommerce']['order_created_to_seller']) && $this->options['woocommerce']['order_created_to_seller'] == 1); |
| 90 |
$has_cart_recovered_to_seller_notification = (isset($this->options['abandoned_carts']['notify_to_admin']) && $this->options['abandoned_carts']['notify_to_admin'] == 1); |
| 91 |
$is_auto_update_disabled = (isset($this->options['disable_auto_update']) && $this->options['disable_auto_update'] == 1); |
| 92 |
$abandoned_carts_waiting_minutes = intval($this->options['abandoned_carts']['waiting_minutes']) ?? 15; |
| 93 |
|
| 94 |
$this->shop = [ |
| 95 |
"plugin_version" => $this->version, |
| 96 |
"name" => $this->options['shop_name'] ?? get_bloginfo('name'), |
| 97 |
"url" => get_bloginfo('url'), |
| 98 |
"email" => $this->options['email'] ?? get_bloginfo('admin_email'), |
| 99 |
"language" => $this->options['language'] ?? get_bloginfo('language'), |
| 100 |
"telephone" => ($this->options['prefix'] ?? '') . ($this->options['telephone'] ?? ''), |
| 101 |
"contact_link" => $this->options['account_info']['contact_link'] ?? null, |
| 102 |
"billing_data" => $billing_data, |
| 103 |
"has_fixed_support_button" => $has_fixed_support_button, |
| 104 |
"has_product_item_listing_button" => $has_product_item_listing_button, |
| 105 |
"has_cart_button" => $has_cart_button, |
| 106 |
"has_single_product_button" => $has_single_product_button, |
| 107 |
"has_abandoned_carts" => $has_abandoned_carts, |
| 108 |
"has_order_updated_notification" => $has_order_updated_notification, |
| 109 |
"has_order_created_notification" => $has_order_created_notification, |
| 110 |
"has_order_deleted_notification" => $has_order_deleted_notification, |
| 111 |
"has_order_note_added_notification" => $has_order_note_added_notification, |
| 112 |
"has_leave_review_notification" => $has_leave_review_notification, |
| 113 |
"has_notifications" => $has_notifications, |
| 114 |
"has_order_created_to_seller_notification" => $has_order_created_to_seller_notification, |
| 115 |
"has_cart_recovered_to_seller_notification" => $has_cart_recovered_to_seller_notification, |
| 116 |
"abandoned_carts_waiting_minutes" => $abandoned_carts_waiting_minutes, |
| 117 |
"is_auto_update_disabled" => $is_auto_update_disabled, |
| 118 |
]; |
| 119 |
|
| 120 |
register_activation_hook(SPOKI_PLUGIN_FILE, array($this, 'activation_reset')); |
| 121 |
register_deactivation_hook(SPOKI_PLUGIN_FILE, array($this, 'deactivation_reset')); |
| 122 |
|
| 123 |
add_action('init', 'spoki_update_po_file'); |
| 124 |
add_action('admin_menu', array($this, 'add_option_menu')); |
| 125 |
add_action('admin_menu', array($this, 'add_submenu'), 99); |
| 126 |
add_filter("plugin_action_links_" . plugin_basename(__FILE__), array($this, 'plugin_settings_link')); |
| 127 |
add_action('wp_enqueue_scripts', array($this, 'add_styles')); |
| 128 |
add_action('admin_enqueue_scripts', array($this, 'add_admin_styles')); |
| 129 |
add_action('admin_enqueue_scripts', array($this, 'add_admin_scripts')); |
| 130 |
add_action('updated_option', array($this, 'on_option_added'), 10, 3); |
| 131 |
add_filter('auto_update_plugin', array($this, 'auto_update_plugin'), 10, 2); |
| 132 |
add_action('spoki_cron_hook', array($this, 'check_secret_status')); |
| 133 |
if (!wp_next_scheduled('spoki_cron_hook')) { |
| 134 |
$this->check_secret_status(); |
| 135 |
wp_schedule_event(time(), 'every_day', 'spoki_cron_hook'); |
| 136 |
} |
| 137 |
|
| 138 |
$this->includes(); |
| 139 |
$this->render_buttons(); |
| 140 |
$this->handle_woocommerce(); |
| 141 |
$this->handle_abandoned_carts(); |
| 142 |
|
| 143 |
add_action('elementor/widgets/widgets_registered', array($this, 'register_elementor_widgets')); |
| 144 |
|
| 145 |
} |
| 146 |
|
| 147 |
/** |
| 148 |
* Include all Spoki required files |
| 149 |
*/ |
| 150 |
private function includes() |
| 151 |
{ |
| 152 |
require_once SPOKI_DIR . 'includes/spoki-functions.php'; |
| 153 |
} |
| 154 |
|
| 155 |
/** |
| 156 |
* Get the setting link of the plugin |
| 157 |
* |
| 158 |
* @param $links |
| 159 |
* @return mixed |
| 160 |
*/ |
| 161 |
public function plugin_settings_link($links) |
| 162 |
{ |
| 163 |
$settings_link = '<a href="admin.php?page=' . SPOKI_PLUGIN_NAME . '">' . __('Settings', SPOKI_PLUGIN_NAME) . '</a>'; |
| 164 |
array_unshift($links, $settings_link); |
| 165 |
return $links; |
| 166 |
} |
| 167 |
|
| 168 |
/** |
| 169 |
* Add the Spoki option to the menu |
| 170 |
*/ |
| 171 |
public function add_option_menu() |
| 172 |
{ |
| 173 |
add_menu_page( |
| 174 |
'Spoki Options', |
| 175 |
"Spoki", |
| 176 |
'manage_options', |
| 177 |
'spoki', |
| 178 |
array($this, 'render_setup_page'), |
| 179 |
plugins_url() . '/' . SPOKI_PLUGIN_NAME . '/assets/images/logo.svg', |
| 180 |
98 |
| 181 |
); |
| 182 |
add_action('admin_init', array($this, 'register_option_var')); |
| 183 |
} |
| 184 |
|
| 185 |
/** |
| 186 |
* Add the Spoki option submenu |
| 187 |
*/ |
| 188 |
function add_submenu() |
| 189 |
{ |
| 190 |
$has_woocommerce = ('woocommerce/woocommerce.php'); |
| 191 |
$badge_seller_notifications = !$this->shop['has_order_created_to_seller_notification'] ? '<span class="update-plugins bg-spoki" style="min-width: max-content"><span class="plugin-count" style="white-space: nowrap; overflow: hidden">' . __('New', "spoki") . '</span></span>' : ''; |
| 192 |
$is_pro = isset($this->options['account_info']['plan']['is_pro']) && $this->options['account_info']['plan']['is_pro'] == true; |
| 193 |
|
| 194 |
add_submenu_page('spoki', __('Statistics', "spoki"), __('Statistics', "spoki"), 'manage_options', "admin.php?page=" . SPOKI_PLUGIN_NAME . "&tab=welcome"); |
| 195 |
add_submenu_page('spoki', __('Buttons', "spoki"), __('Buttons', "spoki"), 'manage_options', "admin.php?page=" . SPOKI_PLUGIN_NAME . "&tab=buttons"); |
| 196 |
add_submenu_page('spoki', __('Customer Notifications', "spoki"), __('Customer Notifications', "spoki"), 'manage_options', "admin.php?page=" . SPOKI_PLUGIN_NAME . "&tab=customer-notifications"); |
| 197 |
add_submenu_page('spoki', __('Seller Notifications', "spoki"), "<div style='display:flex;align-items:center;'>" . __('Seller Notifications', "spoki") . $badge_seller_notifications . "</div>", 'manage_options', "admin.php?page=" . SPOKI_PLUGIN_NAME . "&tab=seller-notifications"); |
| 198 |
add_submenu_page('spoki', __('Abandoned Carts', "spoki"), __('Abandoned Carts', "spoki"), 'manage_options', "admin.php?page=" . SPOKI_PLUGIN_NAME . "&tab=abandoned-carts"); |
| 199 |
add_submenu_page('spoki', __('Settings', "spoki"), __('Settings', "spoki"), 'manage_options', "admin.php?page=" . SPOKI_PLUGIN_NAME . "&tab=settings"); |
| 200 |
add_submenu_page('spoki', __('Invite a friend', "spoki"), __('Invite a friend', "spoki"), 'manage_options', "admin.php?page=" . SPOKI_PLUGIN_NAME . "&tab=invite-a-friend"); |
| 201 |
if (!$is_pro) { |
| 202 |
add_submenu_page('spoki', __('Upgrade', "spoki"), "<span class='color-spoki text-bold'>⇡ " . __('Upgrade', "spoki") . "</span>", 'manage_options', $this->get_plan_link(true)); |
| 203 |
} |
| 204 |
|
| 205 |
if ($has_woocommerce) { |
| 206 |
add_submenu_page( |
| 207 |
'woocommerce', |
| 208 |
__('Spoki', "spoki"), |
| 209 |
__('Spoki', "spoki"), |
| 210 |
'manage_options', |
| 211 |
"admin.php?page=" . SPOKI_PLUGIN_NAME . "&tab=welcome", |
| 212 |
null, |
| 213 |
8 |
| 214 |
); |
| 215 |
} |
| 216 |
|
| 217 |
} |
| 218 |
|
| 219 |
/** |
| 220 |
* Register the Spoki option |
| 221 |
*/ |
| 222 |
public function register_option_var() |
| 223 |
{ |
| 224 |
register_setting('wp-spoki-option', SPOKI_OPTIONS); |
| 225 |
} |
| 226 |
|
| 227 |
/** |
| 228 |
* Add website spoki styles |
| 229 |
*/ |
| 230 |
public function add_styles() |
| 231 |
{ |
| 232 |
$styles = ['buttons']; |
| 233 |
foreach ($styles as $style) { |
| 234 |
echo "<style id='spoki-style-$style'>"; |
| 235 |
include SPOKI_DIR . "assets/css/$style.css"; |
| 236 |
echo "</style>"; |
| 237 |
} |
| 238 |
} |
| 239 |
|
| 240 |
/** |
| 241 |
* Add admin spoki styles |
| 242 |
*/ |
| 243 |
public function add_admin_styles() |
| 244 |
{ |
| 245 |
$styles = ['admin.css', 'onboarding.css', 'account-overview.css', 'spoki-overview.css']; |
| 246 |
|
| 247 |
foreach ($styles as $style) { |
| 248 |
echo "<style>"; |
| 249 |
include_once SPOKI_DIR . 'assets/css/' . $style; |
| 250 |
echo "</style>"; |
| 251 |
} |
| 252 |
|
| 253 |
$this->add_styles(); |
| 254 |
} |
| 255 |
|
| 256 |
/** |
| 257 |
* Add admin spoki scripts |
| 258 |
*/ |
| 259 |
public function add_admin_scripts() |
| 260 |
{ |
| 261 |
$scripts = ['spoki-admin.js', 'spoki-shadowed-buttons.js']; |
| 262 |
|
| 263 |
foreach ($scripts as $script) { |
| 264 |
echo "<script>"; |
| 265 |
include_once SPOKI_DIR . 'assets/js/' . $script; |
| 266 |
echo "</script>"; |
| 267 |
} |
| 268 |
} |
| 269 |
|
| 270 |
/** |
| 271 |
* Enable plugin autoupdate |
| 272 |
*/ |
| 273 |
function auto_update_plugin($update, $item) |
| 274 |
{ |
| 275 |
$plugins = array('spoki'); |
| 276 |
$is_auto_update_disabled = (isset($this->options['disable_auto_update']) && $this->options['disable_auto_update'] == 1); |
| 277 |
if (in_array($item->slug, $plugins) && !$is_auto_update_disabled) |
| 278 |
return true; |
| 279 |
else return $update; |
| 280 |
} |
| 281 |
|
| 282 |
/** |
| 283 |
* Register widgets for Elementor |
| 284 |
*/ |
| 285 |
public function register_elementor_widgets() |
| 286 |
{ |
| 287 |
if (spoki_has_elementor()) { |
| 288 |
include_once SPOKI_DIR . 'widgets/class-elementor-spoki-button.php'; |
| 289 |
\Elementor\Plugin::instance()->widgets_manager->register_widget_type(new \Elementor_Spoki_Button_Widget()); |
| 290 |
} |
| 291 |
} |
| 292 |
|
| 293 |
/** |
| 294 |
* Handle option submit |
| 295 |
* |
| 296 |
* @param $option |
| 297 |
* @param $old_value |
| 298 |
* @param $value |
| 299 |
*/ |
| 300 |
public function on_option_added($option, $old_value, $value) |
| 301 |
{ |
| 302 |
if ($option == SPOKI_OPTIONS) { |
| 303 |
|
| 304 |
/** Onboarding Without WooCommerce */ |
| 305 |
if (isset($value['onboarding']['without_wc'])) { |
| 306 |
$this->update_options($value, [ |
| 307 |
"telephone" => $value['onboarding']['telephone'], |
| 308 |
"prefix" => $value['onboarding']['prefix'], |
| 309 |
"onboarding" => null, |
| 310 |
]); |
| 311 |
$url = admin_url('/admin.php?page=' . SPOKI_PLUGIN_NAME . '&tab=buttons'); |
| 312 |
header("Location: {$url}"); |
| 313 |
exit; |
| 314 |
} |
| 315 |
|
| 316 |
/** Onboarding With WooCommerce */ |
| 317 |
if (isset($value['onboarding']['with_wc'])) { |
| 318 |
$response = $this->create_spoki_account($value['onboarding']['prefix'] . $value['onboarding']['telephone'], $value['onboarding']['email'], $value['onboarding']['shop_name']); |
| 319 |
if (isset($response['secret']) && isset($response['delivery_url'])) { |
| 320 |
$this->update_options($value, [ |
| 321 |
"telephone" => $value['onboarding']['telephone'], |
| 322 |
"prefix" => $value['onboarding']['prefix'], |
| 323 |
"email" => $value['onboarding']['email'], |
| 324 |
"shop_name" => $value['onboarding']['shop_name'], |
| 325 |
"secret" => $response['secret'], |
| 326 |
"delivery_url" => $response['delivery_url'], |
| 327 |
"onboarding" => null, |
| 328 |
"woocommerce" => [ |
| 329 |
"order_created" => 1, |
| 330 |
"order_updated" => 1, |
| 331 |
"order_deleted" => 1, |
| 332 |
"order_note_added" => 1, |
| 333 |
"leave_review" => 1, |
| 334 |
"leave_review_days" => 5, |
| 335 |
"order_created_to_seller" => 1, |
| 336 |
], |
| 337 |
"abandoned_carts" => [ |
| 338 |
"enable_tracking" => 1, |
| 339 |
"notify_to_admin" => 1, |
| 340 |
] |
| 341 |
]); |
| 342 |
$url = admin_url('/admin.php?page=' . SPOKI_PLUGIN_NAME . '&tab=customer-notifications'); |
| 343 |
header("Location: {$url}"); |
| 344 |
exit; |
| 345 |
} |
| 346 |
} |
| 347 |
|
| 348 |
/** Settings updated for registered account */ |
| 349 |
if (isset($value['is_settings'])) { |
| 350 |
$keys_changed = ($value['secret'] != $old_value['secret']) || ($value['delivery_url'] != $old_value['delivery_url']); |
| 351 |
|
| 352 |
$shop_name_changed = $value['shop_name'] != $old_value['shop_name']; |
| 353 |
$email_changed = $value['email'] != $old_value['email']; |
| 354 |
$telephone_changed = $value['telephone'] != $old_value['telephone']; |
| 355 |
$prefix_changed = $value['prefix'] != $old_value['prefix']; |
| 356 |
$contact_link_changed = $value['contact_link'] != $old_value['contact_link']; |
| 357 |
$billing_data_changed = $value['billing_data'] != $old_value['billing_data']; |
| 358 |
|
| 359 |
if ($shop_name_changed || $email_changed || $telephone_changed || $prefix_changed || $contact_link_changed || $billing_data_changed) { |
| 360 |
$this->update_spoki_account($value['prefix'] . $value['telephone'], $value['email'], $value['shop_name'], $value['contact_link'], $value['billing_data']); |
| 361 |
} |
| 362 |
|
| 363 |
if ($keys_changed) { |
| 364 |
$url = admin_url('/admin.php?page=' . SPOKI_PLUGIN_NAME . '&tab=welcome'); |
| 365 |
header("Location: {$url}"); |
| 366 |
exit; |
| 367 |
} |
| 368 |
} |
| 369 |
|
| 370 |
/** Enable all notifications from dashboard */ |
| 371 |
if (isset($value['enable_notifications']) && $value['enable_notifications'] == 1) { |
| 372 |
$this->update_options(get_option(SPOKI_OPTIONS), [ |
| 373 |
"enable_notifications" => 0, |
| 374 |
"woocommerce" => [ |
| 375 |
"order_created" => 1, |
| 376 |
"order_updated" => 1, |
| 377 |
"order_deleted" => 1, |
| 378 |
"order_note_added" => 1, |
| 379 |
"leave_review" => 1, |
| 380 |
"leave_review_days" => 5, |
| 381 |
] |
| 382 |
]); |
| 383 |
$url = admin_url('/admin.php?page=' . SPOKI_PLUGIN_NAME . '&tab=customer-notifications'); |
| 384 |
header("Location: {$url}"); |
| 385 |
exit; |
| 386 |
} |
| 387 |
|
| 388 |
/** Enable order status notifications from dashboard */ |
| 389 |
if (isset($value['enable_order_status_notifications']) && $value['enable_order_status_notifications'] == 1) { |
| 390 |
$this->update_options(get_option(SPOKI_OPTIONS), [ |
| 391 |
"enable_order_status_notifications" => 0, |
| 392 |
"woocommerce" => [ |
| 393 |
"order_created" => 1, |
| 394 |
"order_updated" => 1, |
| 395 |
"order_deleted" => 1, |
| 396 |
] |
| 397 |
]); |
| 398 |
$url = admin_url('/admin.php?page=' . SPOKI_PLUGIN_NAME . '&tab=customer-notifications'); |
| 399 |
header("Location: {$url}"); |
| 400 |
exit; |
| 401 |
} |
| 402 |
|
| 403 |
/** Enable seller notifications from dashboard */ |
| 404 |
if (isset($value['enable_seller_notifications']) && $value['enable_seller_notifications'] == 1) { |
| 405 |
$this->update_options(get_option(SPOKI_OPTIONS), [ |
| 406 |
"enable_seller_notifications" => 0, |
| 407 |
"woocommerce" => [ |
| 408 |
"order_created_to_seller" => 1, |
| 409 |
] |
| 410 |
]); |
| 411 |
$url = admin_url('/admin.php?page=' . SPOKI_PLUGIN_NAME . '&tab=seller-notifications'); |
| 412 |
header("Location: {$url}"); |
| 413 |
exit; |
| 414 |
} |
| 415 |
|
| 416 |
/** Enable leave review notification from dashboard */ |
| 417 |
if (isset($value['enable_leave_review_notification']) && $value['enable_leave_review_notification'] == 1) { |
| 418 |
$this->update_options(get_option(SPOKI_OPTIONS), [ |
| 419 |
"enable_leave_review_notification" => 0, |
| 420 |
"woocommerce" => [ |
| 421 |
"leave_review" => 1, |
| 422 |
"leave_review_days" => 5, |
| 423 |
] |
| 424 |
]); |
| 425 |
$url = admin_url('/admin.php?page=' . SPOKI_PLUGIN_NAME . '&tab=customer-notifications'); |
| 426 |
header("Location: {$url}"); |
| 427 |
exit; |
| 428 |
} |
| 429 |
|
| 430 |
/** Enable enable order note added notification from dashboard */ |
| 431 |
if (isset($value['enable_order_note_added_notification']) && $value['enable_order_note_added_notification'] == 1) { |
| 432 |
$this->update_options(get_option(SPOKI_OPTIONS), [ |
| 433 |
"enable_order_note_added_notification" => 0, |
| 434 |
"woocommerce" => [ |
| 435 |
"order_note_added" => 1, |
| 436 |
] |
| 437 |
]); |
| 438 |
$url = admin_url('/admin.php?page=' . SPOKI_PLUGIN_NAME . '&tab=customer-notifications'); |
| 439 |
header("Location: {$url}"); |
| 440 |
exit; |
| 441 |
} |
| 442 |
} |
| 443 |
} |
| 444 |
|
| 445 |
/** |
| 446 |
* Handle WooCommerce features |
| 447 |
*/ |
| 448 |
public function handle_woocommerce() |
| 449 |
{ |
| 450 |
if (isset($this->options['secret'])) { |
| 451 |
include_once(ABSPATH . 'wp-admin/includes/plugin.php'); |
| 452 |
if (spoki_has_woocommerce()) { |
| 453 |
add_action('woocommerce_order_status_changed', array($this, 'send_woocommerce_order_created_or_updated_alert'), 1, 3); |
| 454 |
add_action('woocommerce_cancelled_order', array($this, 'send_woocommerce_order_deleted_alert'), 10, 3); |
| 455 |
add_action('woocommerce_trash_order', array($this, 'send_woocommerce_order_deleted_alert'), 10, 3); |
| 456 |
add_action('woocommerce_order_note_added', array($this, 'send_woocommerce_note_alert'), 10, 2); |
| 457 |
add_action('woocommerce_order_status_completed', array($this, 'send_woocommerce_review_alert'), 10, 2); |
| 458 |
|
| 459 |
if (isset($this->options['woocommerce']['cart_button_hide_checkout_button_check']) && $this->options['woocommerce']['cart_button_hide_checkout_button_check'] == 1) { |
| 460 |
add_action('woocommerce_proceed_to_checkout', array($this, 'disable_checkout_button'), 1); |
| 461 |
} |
| 462 |
} |
| 463 |
} |
| 464 |
$this->fetch_secret_status(); |
| 465 |
} |
| 466 |
|
| 467 |
/** |
| 468 |
* Handle WooCommerce abandoned carts feature |
| 469 |
*/ |
| 470 |
public function handle_abandoned_carts() |
| 471 |
{ |
| 472 |
$Abandonment = Spoki_Abandoned_Carts::instance(); |
| 473 |
if (isset($this->options['abandoned_carts']['enable_tracking']) && $this->options['abandoned_carts']['enable_tracking'] == 1) { |
| 474 |
$this->initialize_cart_abandonment_tables(); |
| 475 |
$Abandonment->set_spoki_setting_by_meta("plugin_activated", "true"); |
| 476 |
do_action('spoki_cartflow_ca_init'); |
| 477 |
} elseif (wp_next_scheduled('spoki_abandoned_carts_cron_hook')) { |
| 478 |
# Unschedule hook for versions <= v2.8.1 |
| 479 |
$Abandonment->unschedule_hook(); |
| 480 |
} |
| 481 |
} |
| 482 |
|
| 483 |
/** |
| 484 |
* Create new database tables for plugin updates. |
| 485 |
* |
| 486 |
* @return void |
| 487 |
*/ |
| 488 |
public function initialize_cart_abandonment_tables() |
| 489 |
{ |
| 490 |
include_once SPOKI_DIR . 'modules/abandoned-carts/spoki-abandoned-carts-db.php'; |
| 491 |
$db = Spoki_Abandoned_Carts_Db::instance(); |
| 492 |
$db->create_tables(); |
| 493 |
$db->init_tables(); |
| 494 |
} |
| 495 |
|
| 496 |
/** |
| 497 |
* Send the Spoki notification for order status created or updated |
| 498 |
* |
| 499 |
* @param $order_get_id |
| 500 |
* @param $from |
| 501 |
* @param $to |
| 502 |
*/ |
| 503 |
public function send_woocommerce_order_created_or_updated_alert($order_get_id, $from, $to) |
| 504 |
{ |
| 505 |
/** A new order has been created */ |
| 506 |
if (($from === 'pending' || $from === 'on_hold' || $from === 'failed') && $to === 'processing') { |
| 507 |
$this->send_woocommerce_order_created_alert($order_get_id); |
| 508 |
return; |
| 509 |
} |
| 510 |
|
| 511 |
/** The order has been updated */ |
| 512 |
if ($to === 'completed' || $to === 'refunded' || $to === 'processing') { |
| 513 |
$this->send_woocommerce_order_alert($order_get_id, 'order.updated'); |
| 514 |
} |
| 515 |
} |
| 516 |
|
| 517 |
/** |
| 518 |
* Send the Spoki notification for review |
| 519 |
* |
| 520 |
* @param $order_get_id |
| 521 |
*/ |
| 522 |
public function send_woocommerce_review_alert($order_get_id) |
| 523 |
{ |
| 524 |
$review_link = (isset($this->options['woocommerce']['leave_review_link']) && $this->options['woocommerce']['leave_review_link'] != "") ? $this->options['woocommerce']['leave_review_link'] : ""; |
| 525 |
$review_link_days = (isset($this->options['woocommerce']['leave_review_days']) && $this->options['woocommerce']['leave_review_days'] != "") ? $this->options['woocommerce']['leave_review_days'] : 5; |
| 526 |
$this->send_woocommerce_order_alert($order_get_id, 'order.review', ["review_link" => $review_link, "delay" => intval($review_link_days) * 24 * 60 * 60]); |
| 527 |
} |
| 528 |
|
| 529 |
/** |
| 530 |
* Notify the Abandoned Cart Info Spoki notification |
| 531 |
* |
| 532 |
* @param $session_id |
| 533 |
* @param $checkoutDetails |
| 534 |
* @param $topic |
| 535 |
* @return bool |
| 536 |
*/ |
| 537 |
public function notify_abandoned_cart_info($session_id, $checkoutDetails, $topic): bool |
| 538 |
{ |
| 539 |
$other_fields = unserialize($checkoutDetails->other_fields); |
| 540 |
$parts = explode(',', $other_fields['spoki_location']); |
| 541 |
$country = $parts[0]; |
| 542 |
$data = [ |
| 543 |
"customer" => [ |
| 544 |
'email' => $checkoutDetails->email, |
| 545 |
'phone' => sanitize_text_field($other_fields['spoki_phone_number']), |
| 546 |
'country' => sanitize_text_field($country), |
| 547 |
'name' => sanitize_text_field($other_fields['spoki_first_name']) . ' ' . sanitize_text_field($other_fields['spoki_last_name']), |
| 548 |
], |
| 549 |
"checkout" => [ |
| 550 |
"checkout_url" => get_permalink($checkoutDetails->checkout_id) . '?session_id=' . $checkoutDetails->session_id, |
| 551 |
"checkout_info" => $other_fields, |
| 552 |
"cart_contacted_url" => get_bloginfo('url') . '/wp-json/api/v1/setCartAsContacted', |
| 553 |
"total" => $checkoutDetails->cart_total, |
| 554 |
"currency" => get_woocommerce_currency(), |
| 555 |
], |
| 556 |
"session_id" => $session_id, |
| 557 |
]; |
| 558 |
return $this->spoki_send($data, $topic); |
| 559 |
} |
| 560 |
|
| 561 |
/** |
| 562 |
* Send the Spoki notification for order created |
| 563 |
* |
| 564 |
* @param $order_get_id |
| 565 |
*/ |
| 566 |
public function send_woocommerce_order_created_alert($order_get_id) |
| 567 |
{ |
| 568 |
$this->send_woocommerce_order_alert($order_get_id, 'order.created'); |
| 569 |
} |
| 570 |
|
| 571 |
/** |
| 572 |
* Send the Spoki notification for order deleted |
| 573 |
* |
| 574 |
* @param $order_get_id |
| 575 |
*/ |
| 576 |
public function send_woocommerce_order_deleted_alert($order_get_id) |
| 577 |
{ |
| 578 |
$this->send_woocommerce_order_alert($order_get_id, 'order.deleted'); |
| 579 |
} |
| 580 |
|
| 581 |
/** |
| 582 |
* Send the Spoki notification for order status |
| 583 |
* |
| 584 |
* @param $order_get_id |
| 585 |
* @param $topic |
| 586 |
* @param $additional_data |
| 587 |
*/ |
| 588 |
public function send_woocommerce_order_alert($order_get_id, $topic, $additional_data = []) |
| 589 |
{ |
| 590 |
$order = wc_get_order($order_get_id); |
| 591 |
$session = []; |
| 592 |
if (WC()->session && $topic == 'order.created') { |
| 593 |
$session = ['session_id' => WC()->session->get('spoki_session_id')]; |
| 594 |
} |
| 595 |
$order_data = array_merge(((isset($order) && false != $order ? $order->get_data() : ["id" => $order_get_id])), $additional_data); |
| 596 |
$parts = explode(',', $order_data['billing']['country'] ?? ''); |
| 597 |
$country = $parts[0]; |
| 598 |
$customer = [ |
| 599 |
'email' => $order_data['billing']['email'] ?? '', |
| 600 |
'phone' => $order_data['billing']['phone'] ?? '', |
| 601 |
'country' => $country ?? '', |
| 602 |
'name' => ($order_data['billing']['first_name'] ?? '') . ' ' . ($order_data['billing']['last_name'] ?? ''), |
| 603 |
]; |
| 604 |
$this->spoki_send(array_merge([ |
| 605 |
"order" => $order_data, |
| 606 |
"customer" => $customer, |
| 607 |
], $session), $topic); |
| 608 |
} |
| 609 |
|
| 610 |
/** |
| 611 |
* Send the Spoki notification for tracking number |
| 612 |
* |
| 613 |
* @param $id |
| 614 |
* @param $order |
| 615 |
*/ |
| 616 |
public function send_woocommerce_note_alert($id, $order) |
| 617 |
{ |
| 618 |
$comment = get_comment($id); |
| 619 |
if (isset($comment->comment_content)) { |
| 620 |
$is_gls_tracking = substr(strtolower($comment->comment_content), 0, 4) == '[gls'; |
| 621 |
$is_user_tracking = substr(strtolower($comment->comment_content), 0, 10) == '[tracking]'; |
| 622 |
|
| 623 |
/** Send the message only if it is a tracking order note */ |
| 624 |
if ($comment->comment_type == 'order_note' && ($is_gls_tracking || $is_user_tracking)) { |
| 625 |
$order_data = $order->get_data(); |
| 626 |
$this->send_woocommerce_order_alert($order_data['id'], 'order.tracking', ["note" => $comment]); |
| 627 |
} |
| 628 |
} |
| 629 |
} |
| 630 |
|
| 631 |
/** |
| 632 |
* Send the Spoki notification |
| 633 |
* |
| 634 |
* @param $data |
| 635 |
* @return bool |
| 636 |
*/ |
| 637 |
public function spoki_send($data, $topic): bool |
| 638 |
{ |
| 639 |
$shop = ["shop" => $this->shop]; |
| 640 |
|
| 641 |
$request_params = array( |
| 642 |
"headers" => array( |
| 643 |
"Authorization" => $this->options['secret'], |
| 644 |
"language" => $this->shop['language'], |
| 645 |
"X-Wc-Webhook-Topic" => $topic, |
| 646 |
), |
| 647 |
"body" => wp_json_encode(array_merge($data, $shop)), |
| 648 |
"sslverify" => false, |
| 649 |
"timeout" => 60, |
| 650 |
); |
| 651 |
$response = wp_remote_post($this->options['delivery_url'], $request_params); |
| 652 |
$code = wp_remote_retrieve_response_code($response); |
| 653 |
return $code == 200; |
| 654 |
} |
| 655 |
|
| 656 |
/** |
| 657 |
* Create a new Spoki Free account |
| 658 |
* |
| 659 |
* @param $telephone |
| 660 |
* @param $email |
| 661 |
* @param $shop_name |
| 662 |
* @return array |
| 663 |
*/ |
| 664 |
private function create_spoki_account($telephone, $email, $shop_name): array |
| 665 |
{ |
| 666 |
$request_params = array( |
| 667 |
"headers" => array("Authorization" => $this->options['secret'], "language" => $this->shop['language']), |
| 668 |
"body" => [ |
| 669 |
"phone" => $telephone, |
| 670 |
"email" => $email, |
| 671 |
"name" => $shop_name, |
| 672 |
], |
| 673 |
"sslverify" => false, |
| 674 |
"timeout" => 60, |
| 675 |
); |
| 676 |
|
| 677 |
$response = wp_remote_post($this->api_enable_flex, $request_params); |
| 678 |
$code = wp_remote_retrieve_response_code($response); |
| 679 |
|
| 680 |
if ($code >= 200 && $code < 300) { |
| 681 |
$data = json_decode(wp_remote_retrieve_body($response), true); |
| 682 |
return [ |
| 683 |
"secret" => isset($data['secret']) ? $data['secret'] : null, |
| 684 |
"delivery_url" => isset($data['delivery_url']) ? $data['delivery_url'] : null, |
| 685 |
]; |
| 686 |
} |
| 687 |
return []; |
| 688 |
} |
| 689 |
|
| 690 |
|
| 691 |
/** |
| 692 |
* Update a Spoki account |
| 693 |
* |
| 694 |
* @param $phone |
| 695 |
* @param $email |
| 696 |
* @param $shop_name |
| 697 |
* @param $contact_link |
| 698 |
* @param $billing_data |
| 699 |
*/ |
| 700 |
private function update_spoki_account($phone, $email, $shop_name, $contact_link, $billing_data = []) |
| 701 |
{ |
| 702 |
$request_params = array( |
| 703 |
"headers" => array("Authorization" => $this->options['secret'], "language" => $this->shop['language']), |
| 704 |
"body" => [ |
| 705 |
"phone" => $phone ?: '', |
| 706 |
"email" => $email ?: '', |
| 707 |
"name" => $shop_name ?: '', |
| 708 |
"contact_link" => $contact_link ?: '', |
| 709 |
"zip_code" => $billing_data['zip_code'] ?: '', |
| 710 |
"province" => $billing_data['province'] ?: '', |
| 711 |
"country" => $billing_data['country'] ?: '', |
| 712 |
"route" => $billing_data['route'] ?: '', |
| 713 |
"city" => $billing_data['city'] ?: '', |
| 714 |
"vat_number" => $billing_data['vat_number'] ?: '', |
| 715 |
"vat_name" => $billing_data['vat_name'] ?: '', |
| 716 |
"c_f" => $billing_data['c_f'] ?: '', |
| 717 |
"pec" => $billing_data['pec'] ?: '', |
| 718 |
"sid" => $billing_data['sid'] ?: '', |
| 719 |
], |
| 720 |
"sslverify" => false, |
| 721 |
"timeout" => 60, |
| 722 |
); |
| 723 |
wp_remote_post($this->api_account, $request_params); |
| 724 |
} |
| 725 |
|
| 726 |
/** |
| 727 |
* Fetch and update the account_info |
| 728 |
*/ |
| 729 |
public function fetch_account_info() |
| 730 |
{ |
| 731 |
$request_params = [ |
| 732 |
"headers" => [ |
| 733 |
"Authorization" => $this->options['secret'], |
| 734 |
"language" => $this->shop['language'] |
| 735 |
], |
| 736 |
"sslverify" => false, |
| 737 |
"timeout" => 60, |
| 738 |
]; |
| 739 |
$response = wp_remote_get($this->api_plan, $request_params); |
| 740 |
$account_info = json_decode(wp_remote_retrieve_body($response), true); |
| 741 |
$this->update_options(get_option(SPOKI_OPTIONS), ["account_info" => $account_info]); |
| 742 |
return $account_info; |
| 743 |
} |
| 744 |
|
| 745 |
/** |
| 746 |
* Check the status of the spoki keys |
| 747 |
* |
| 748 |
* @return array|WP_Error |
| 749 |
*/ |
| 750 |
public function check_spoki_status() |
| 751 |
{ |
| 752 |
$secret = $this->options['secret'] ?? null; |
| 753 |
$has_woocommerce = spoki_has_woocommerce(); |
| 754 |
|
| 755 |
$body = [ |
| 756 |
"is_plugin_active" => true, |
| 757 |
"plugin_version" => $this->version, |
| 758 |
"url" => $this->shop['url'], |
| 759 |
"name" => $this->shop['name'], |
| 760 |
"language" => $this->shop['language'], |
| 761 |
"email" => $this->shop['email'], |
| 762 |
"telephone" => $this->shop['telephone'], |
| 763 |
"has_woocommerce" => $has_woocommerce, |
| 764 |
"is_widget_fixed_enabled" => $this->shop['has_fixed_support_button'], |
| 765 |
"is_widget_woo_shop_enabled" => $this->shop['has_product_item_listing_button'], |
| 766 |
"is_widget_woo_item_enabled" => $this->shop['has_single_product_button'], |
| 767 |
"is_widget_woo_cart_enabled" => $this->shop['has_cart_button'], |
| 768 |
"is_widget_woo_checkout_enabled" => $this->shop['has_cart_button'], |
| 769 |
"is_abandoned_carts_enabled" => $this->shop['has_abandoned_carts'], |
| 770 |
"is_woo_send_enabled" => $has_woocommerce && $this->shop['has_notifications'], |
| 771 |
"is_order_updated_notification_enabled" => $this->shop['has_order_updated_notification'], |
| 772 |
"is_order_created_notification_enabled" => $this->shop['has_order_created_notification'], |
| 773 |
"is_order_deleted_notification_enabled" => $this->shop['has_order_deleted_notification'], |
| 774 |
"is_order_note_added_notification_enabled" => $this->shop['has_order_note_added_notification'], |
| 775 |
"is_leave_review_notification_enabled" => $this->shop['has_leave_review_notification'], |
| 776 |
"has_cart_recovered_to_seller_notification" => $this->shop['has_cart_recovered_to_seller_notification'], |
| 777 |
"contact_link" => $this->shop['contact_link'] ?: '', |
| 778 |
"zip_code" => $this->shop['billing_data']['zip_code'] ?: '', |
| 779 |
"province" => $this->shop['billing_data']['province'] ?: '', |
| 780 |
"country" => $this->shop['billing_data']['country'] ?: '', |
| 781 |
"route" => $this->shop['billing_data']['route'] ?: '', |
| 782 |
"city" => $this->shop['billing_data']['city'] ?: '', |
| 783 |
"vat_number" => $this->shop['billing_data']['vat_number'] ?: '', |
| 784 |
"vat_name" => $this->shop['billing_data']['vat_name'] ?: '', |
| 785 |
"c_f" => $this->shop['billing_data']['c_f'] ?: '', |
| 786 |
"pec" => $this->shop['billing_data']['pec'] ?: '', |
| 787 |
"sid" => $this->shop['billing_data']['sid'] ?: '', |
| 788 |
]; |
| 789 |
|
| 790 |
if ($this->shop['has_abandoned_carts']) { |
| 791 |
$spoki_abandoned_carts = Spoki_Abandoned_Carts::instance(); |
| 792 |
$abandoned_report = $spoki_abandoned_carts->get_report_by_type(SPOKI_CART_ABANDONED_ORDER); |
| 793 |
$recovered_report = $spoki_abandoned_carts->get_report_by_type(SPOKI_CART_COMPLETED_ORDER); |
| 794 |
$body["abandoned_carts_reports"] = [ |
| 795 |
"abandoned" => $abandoned_report, |
| 796 |
"recovered" => $recovered_report, |
| 797 |
]; |
| 798 |
} |
| 799 |
|
| 800 |
$request_params = [ |
| 801 |
"headers" => [ |
| 802 |
"Authorization" => $secret, |
| 803 |
"language" => $this->shop['language'], |
| 804 |
], |
| 805 |
"body" => $body, |
| 806 |
"sslverify" => false, |
| 807 |
"timeout" => 60, |
| 808 |
]; |
| 809 |
return wp_remote_post($this->api_status, $request_params); |
| 810 |
} |
| 811 |
|
| 812 |
/** |
| 813 |
* Render the admin setup page |
| 814 |
*/ |
| 815 |
public function render_setup_page() |
| 816 |
{ |
| 817 |
require_once SPOKI_DIR . 'includes/page-setup.php'; |
| 818 |
$this->render_components(); |
| 819 |
} |
| 820 |
|
| 821 |
|
| 822 |
/** |
| 823 |
* Render the Spoki Components |
| 824 |
*/ |
| 825 |
public function render_components() |
| 826 |
{ |
| 827 |
$components = ['abandoned-carts-info-dialog', 'customer-notifications-info-dialog', 'buttons-info-dialog']; |
| 828 |
foreach ($components as $component) { |
| 829 |
include_once SPOKI_DIR . "components/$component.php"; |
| 830 |
} |
| 831 |
} |
| 832 |
|
| 833 |
/** |
| 834 |
* Render the WhatsApp buttons in the website |
| 835 |
*/ |
| 836 |
public function render_buttons() |
| 837 |
{ |
| 838 |
$has_fixed_support_button = isset($this->options['buttons']['fixed_support_button_check']) && $this->options['buttons']['fixed_support_button_check'] == 1; |
| 839 |
$has_product_item_listing_button = isset($this->options['woocommerce']['product_item_listing_button_check']) && $this->options['woocommerce']['product_item_listing_button_check'] == 1; |
| 840 |
$has_cart_button = isset($this->options['woocommerce']['cart_button_check']) && $this->options['woocommerce']['cart_button_check'] == 1; |
| 841 |
$has_single_product_button = isset($this->options['woocommerce']['single_product_button_check']) && $this->options['woocommerce']['single_product_button_check'] == 1; |
| 842 |
|
| 843 |
// Floating Button |
| 844 |
if ($has_fixed_support_button) { |
| 845 |
add_action('wp_footer', array($this, 'render_floating_button'), 1); |
| 846 |
} |
| 847 |
|
| 848 |
// Product Item Listing Button |
| 849 |
if ($has_product_item_listing_button) { |
| 850 |
add_action('woocommerce_after_shop_loop_item', array($this, 'render_product_item_listing_button'), 99); |
| 851 |
} |
| 852 |
|
| 853 |
// Cart Page Button |
| 854 |
if ($has_cart_button) { |
| 855 |
add_action('woocommerce_after_cart_totals', array($this, 'render_cart_button'), 99); |
| 856 |
} |
| 857 |
|
| 858 |
// Single Product Page Button |
| 859 |
if ($has_single_product_button) { |
| 860 |
$position = isset($this->options['woocommerce']['single_product_button_position']) ? $this->options['woocommerce']['single_product_button_position'] : 'after_atc'; |
| 861 |
switch ($position) { |
| 862 |
case 'under_atc': |
| 863 |
add_action('woocommerce_after_add_to_cart_form', array($this, 'render_single_product_button'), 99); |
| 864 |
break; |
| 865 |
case 'after_shortdesc': |
| 866 |
add_action('woocommerce_before_add_to_cart_form', array($this, 'render_single_product_button'), 99); |
| 867 |
break; |
| 868 |
case 'after_atc': |
| 869 |
default: |
| 870 |
add_action('woocommerce_after_add_to_cart_button', array($this, 'render_single_product_button'), 99); |
| 871 |
break; |
| 872 |
} |
| 873 |
} |
| 874 |
|
| 875 |
/** |
| 876 |
* Render the spoki button wherever you want using the shortcode |
| 877 |
* @param $attrs |
| 878 |
* @param null $content |
| 879 |
*/ |
| 880 |
function spoki_button_shortcode($attrs, $content = null) |
| 881 |
{ |
| 882 |
$phone = $attrs['phone'] ?? Spoki()->shop['telephone']; |
| 883 |
$cta = $attrs['cta'] ?? ''; |
| 884 |
$title = $attrs['title'] ?? ''; |
| 885 |
$final_message = urlencode($attrs['message'] ?? ''); |
| 886 |
$additional_class = $attrs['additional_class'] ?? ''; |
| 887 |
$type = 5; |
| 888 |
$color = $attrs['color'] ?? null; |
| 889 |
$border_type = $attrs['border_type'] ?? null; |
| 890 |
$margin_top = $attrs['margin_top'] ?? null; |
| 891 |
$margin_left = $attrs['margin_left'] ?? null; |
| 892 |
$margin_right = $attrs['margin_right'] ?? null; |
| 893 |
$margin_bottom = $attrs['margin_bottom'] ?? null; |
| 894 |
$font_size = $attrs['font_size'] ?? null; |
| 895 |
Spoki()->render_relative_button($phone, $cta, $title, $final_message, $additional_class, $type, $color, $border_type, $margin_top, $margin_bottom, $margin_left, $margin_right, $font_size, ''); |
| 896 |
} |
| 897 |
|
| 898 |
add_shortcode('spoki_button', 'spoki_button_shortcode'); |
| 899 |
|
| 900 |
add_action('wp_footer', array($this, 'render_shadowed_buttons')); |
| 901 |
} |
| 902 |
|
| 903 |
public function disable_checkout_button() |
| 904 |
{ |
| 905 |
remove_action('woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20); |
| 906 |
} |
| 907 |
|
| 908 |
/** |
| 909 |
* |
| 910 |
*/ |
| 911 |
public function render_shadowed_buttons() |
| 912 |
{ |
| 913 |
echo "<script>"; |
| 914 |
include_once SPOKI_DIR . 'assets/js/spoki-shadowed-buttons.js'; |
| 915 |
echo "</script>"; |
| 916 |
} |
| 917 |
|
| 918 |
/** |
| 919 |
* Render the WhatsApp FAB on the website in every page |
| 920 |
*/ |
| 921 |
public function render_floating_button() |
| 922 |
{ |
| 923 |
if (isset($this->options['telephone']) && $this->options['telephone'] != '') { |
| 924 |
|
| 925 |
/** Check visibility conditions */ |
| 926 |
$hide_on_posts = isset($this->options['buttons']['fixed_support_button_hide_post_page']) && $this->options['buttons']['fixed_support_button_hide_post_page'] == 1; |
| 927 |
if ($hide_on_posts && is_single() && 'post' == get_post_type()) { |
| 928 |
return; |
| 929 |
} |
| 930 |
$hide_on_pages = isset($this->options['buttons']['fixed_support_button_hide_single_page']) && $this->options['buttons']['fixed_support_button_hide_single_page'] == 1; |
| 931 |
if ($hide_on_pages && is_page() && 'page' == get_post_type()) { |
| 932 |
return; |
| 933 |
} |
| 934 |
$hide_on_shop = isset($this->options['buttons']['fixed_support_button_hide_shop_page']) && $this->options['buttons']['fixed_support_button_hide_shop_page'] == 1; |
| 935 |
if ($hide_on_shop && is_shop()) { |
| 936 |
return; |
| 937 |
} |
| 938 |
$hide_on_product = isset($this->options['buttons']['fixed_support_button_hide_product_page']) && $this->options['buttons']['fixed_support_button_hide_product_page'] == 1; |
| 939 |
if ($hide_on_product && is_product()) { |
| 940 |
return; |
| 941 |
} |
| 942 |
$hide_on_cart = isset($this->options['buttons']['fixed_support_button_hide_cart_page']) && $this->options['buttons']['fixed_support_button_hide_cart_page'] == 1; |
| 943 |
if ($hide_on_cart && is_cart()) { |
| 944 |
return; |
| 945 |
} |
| 946 |
$hide_on_checkout = isset($this->options['buttons']['fixed_support_button_hide_checkout_page']) && $this->options['buttons']['fixed_support_button_hide_checkout_page'] == 1; |
| 947 |
if ($hide_on_checkout && (is_checkout() || is_checkout_pay_page())) { |
| 948 |
return; |
| 949 |
} |
| 950 |
|
| 951 |
|
| 952 |
/** Can render, go on */ |
| 953 |
$prefix = isset($this->options['prefix']) ? $this->options['prefix'] : ''; |
| 954 |
$phone = $prefix . $this->options['telephone']; |
| 955 |
$text = $this->options['buttons']['fixed_support_button_text']; |
| 956 |
$position = $this->options['buttons']['fixed_support_button_position'] == 'Left' ? 'left' : 'right'; |
| 957 |
$border_type = isset($this->options['buttons']['fixed_support_button_border']) ? $this->options['buttons']['fixed_support_button_border'] : 'circle'; |
| 958 |
$size = isset($this->options['buttons']['fixed_support_button_size']) ? $this->options['buttons']['fixed_support_button_size'] : '50'; |
| 959 |
$icon_size = '65%'; |
| 960 |
$border_radius = '50%'; |
| 961 |
if ($border_type == 'squared') { |
| 962 |
$border_radius = '0'; |
| 963 |
} elseif ($border_type == 'rounded') { |
| 964 |
$border_radius = '8px'; |
| 965 |
} |
| 966 |
$color = isset($this->options['buttons']['fixed_support_button_color']) ? $this->options['buttons']['fixed_support_button_color'] : '#23D366'; |
| 967 |
$bottom_space = isset($this->options['buttons']['fixed_support_button_bottom_space']) ? $this->options['buttons']['fixed_support_button_bottom_space'] : '12'; |
| 968 |
$side_space = isset($this->options['buttons']['fixed_support_button_side_space']) ? $this->options['buttons']['fixed_support_button_side_space'] : '12'; |
| 969 |
$furl = get_bloginfo('url'); |
| 970 |
$wa_link = SPOKI_BASE_API_BUTTONS . "?type=1&phone=$phone&text=" . urlencode($text) . "&furl=$furl"; |
| 971 |
|
| 972 |
$spoki_fixed_btn_label = ""; |
| 973 |
$has_label = isset($this->options['buttons']['fixed_support_button_show_label']) && $this->options['buttons']['fixed_support_button_show_label'] == 1; |
| 974 |
if ($has_label) { |
| 975 |
$show_on_hover = (isset($this->options['buttons']['fixed_support_button_show_label_on_hover']) && $this->options['buttons']['fixed_support_button_show_label_on_hover'] == 1) ? 'hide-not-hover' : ''; |
| 976 |
$label_space = intval($size) + 12; |
| 977 |
$label_content = (isset($this->options['buttons']['fixed_support_button_label_content']) && $this->options['buttons']['fixed_support_button_label_content'] != "") ? $this->options['buttons']['fixed_support_button_label_content'] : __('Chat with us 👋', "spoki"); |
| 978 |
$label_font_size = (isset($this->options['buttons']['fixed_support_button_label_font_size']) && $this->options['buttons']['fixed_support_button_label_font_size'] != "") ? $this->options['buttons']['fixed_support_button_label_font_size'] : '16'; |
| 979 |
$label_text_color = isset($this->options['buttons']['fixed_support_button_label_text_color']) ? $this->options['buttons']['fixed_support_button_label_text_color'] : '#333333'; |
| 980 |
$label_background_color = isset($this->options['buttons']['fixed_support_button_label_background_color']) ? $this->options['buttons']['fixed_support_button_label_background_color'] : '#FFFFFF'; |
| 981 |
$label_border_radius = $border_type == 'squared' ? '0' : '10'; |
| 982 |
$label_delay = (intval((isset($this->options['buttons']['fixed_support_button_label_delay']) && $this->options['buttons']['fixed_support_button_label_delay'] != "") ? $this->options['buttons']['fixed_support_button_label_delay'] : '0') * 1000) + 1000; |
| 983 |
$spoki_fixed_btn_label = "<div class='spoki-fixed-btn-label $show_on_hover' style='display:none;$position:{$label_space}px;font-size:{$label_font_size}px;color:$label_text_color;background-color:$label_background_color;border-radius:{$label_border_radius}px;'>$label_content</div><script>(function (d) {setTimeout(function (){try {const shadowedButton = d.querySelector('#spoki-shadowed-fixed-button'); if (shadowedButton) {shadowedButton.shadowRoot.querySelector('.spoki-fixed-btn-label').style.display ='';}} catch (e) {console.log(e)}}, $label_delay)})(document)</script>"; |
| 984 |
} |
| 985 |
|
| 986 |
$spoki_fixed_btn_popup = ""; |
| 987 |
$has_popup = isset($this->options['buttons']['fixed_support_button_show_popup']) && $this->options['buttons']['fixed_support_button_show_popup'] == 1; |
| 988 |
if ($has_popup) { |
| 989 |
$spoki_fixed_btn_popup_delay = (intval((isset($this->options['buttons']['fixed_support_button_popup_delay']) && $this->options['buttons']['fixed_support_button_popup_delay'] != "") ? $this->options['buttons']['fixed_support_button_popup_delay'] : '0') * 1000) + 1000; |
| 990 |
$spoki_fixed_btn_popup = "<span class='spoki-fixed-btn-popup' style='display: none;'>1</span><script>(function (d) {setTimeout(function (){try {const shadowedButton = d.querySelector('#spoki-shadowed-fixed-button'); if (shadowedButton) {shadowedButton.shadowRoot.querySelector('.spoki-fixed-btn-popup').style.display ='';}} catch (e) {console.log(e)}}, $spoki_fixed_btn_popup_delay)})(document)</script>"; |
| 991 |
} |
| 992 |
|
| 993 |
$hidden_mobile = isset($this->options['buttons']['fixed_support_button_hide_mobile']) && $this->options['buttons']['fixed_support_button_hide_mobile'] == 1 ? "hidden-mobile" : ""; |
| 994 |
$hidden_tablet = isset($this->options['buttons']['fixed_support_button_hide_tablet']) && $this->options['buttons']['fixed_support_button_hide_tablet'] == 1 ? "hidden-tablet" : ""; |
| 995 |
$hidden_desktop = isset($this->options['buttons']['fixed_support_button_hide_desktop']) && $this->options['buttons']['fixed_support_button_hide_desktop'] == 1 ? "hidden-desktop" : ""; |
| 996 |
$class = "$hidden_mobile $hidden_tablet $hidden_desktop"; |
| 997 |
|
| 998 |
$chat_widget = ""; |
| 999 |
$has_chat_widget = isset($this->options['buttons']['fixed_support_button_show_chat_widget']) && $this->options['buttons']['fixed_support_button_show_chat_widget'] == 1; |
| 1000 |
if ($has_chat_widget) { |
| 1001 |
$background_image_url = plugins_url() . '/' . SPOKI_PLUGIN_NAME . '/assets/images/wa-background.jpeg'; |
| 1002 |
$from_message = $this->options['buttons']['fixed_support_button_chat_widget_message']; |
| 1003 |
$send_icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="currentColor" d="M1.101 21.757L23.8 12.028 1.101 2.3l.011 7.912 13.623 1.816-13.623 1.817-.011 7.912z"></path></svg>'; |
| 1004 |
$chat_widget_delay = intval((isset($this->options['buttons']['fixed_support_button_chat_widget_delay']) && $this->options['buttons']['fixed_support_button_chat_widget_delay'] != "") ? $this->options['buttons']['fixed_support_button_chat_widget_delay'] : '0') * 1000; |
| 1005 |
$chat_widget_delay_script = ""; |
| 1006 |
if ($chat_widget_delay != 0) { |
| 1007 |
$chat_widget_delay = $chat_widget_delay + 1000; |
| 1008 |
$chat_widget_delay_script = "<script>(function (d) {setTimeout(function (){try {const shadowedButton = d.querySelector('#spoki-shadowed-fixed-button'); if (shadowedButton) {shadowedButton.shadowRoot.querySelector('#spoki-chat-preview').classList.remove('hidden')}} catch (e) {console.log(e)}}, $chat_widget_delay)})(document)</script>"; |
| 1009 |
} |
| 1010 |
$chat_widget_script = "<script>(function (d) {setTimeout(function(){const shadowedButton = d.querySelector('#spoki-shadowed-fixed-button'); if (shadowedButton) {shadowedButton.shadowRoot.querySelector('#spoki-chat-link').addEventListener('click', function(e){e.preventDefault();document.querySelector('#spoki-shadowed-fixed-button').shadowRoot.querySelector('#spoki-chat-preview').classList.toggle('hidden')})}}, 1000)})(document)</script>$chat_widget_delay_script"; |
| 1011 |
$link = SPOKI_BASE_API_BUTTONS; |
| 1012 |
$furl = get_bloginfo('url'); |
| 1013 |
$chat_widget = "<div id='spoki-chat-preview' class='hidden' style='bottom:{$size}px;background-image: url(\"{$background_image_url}\")'><div class='spoki-chat-preview-chat-message'>{$from_message}</div><div id='spoki-chat-preview-footer'><form method='get' target='_blank' action='$link'><input type='hidden' name='phone' value='{$phone}'/><input type='hidden' name='furl' value='{$furl}'/><input type='hidden' name='type' value='1'/><input id='spoki-chat-preview-message' type='text' name='text' value='$text' /><button id='spoki-chat-preview-send' type='submit'>{$send_icon}</button></form></div></div>$chat_widget_script"; |
| 1014 |
} |
| 1015 |
|
| 1016 |
echo "<div id='spoki-shadowed-fixed-button' class='spoki-shadowed-button'><div id='spoki-fixed-btn' class='$class' style='$position:{$side_space}px;bottom:{$bottom_space}px;'>{$chat_widget}{$spoki_fixed_btn_label}{$spoki_fixed_btn_popup}<a id='spoki-chat-link' style='background-color:{$color};border-radius:$border_radius;height:{$size}px;width:{$size}px;' href='$wa_link' target='_blank' rel='nofollow'>" . spoki_get_wa_logo($size) . "</a></div></div>"; |
| 1017 |
} |
| 1018 |
} |
| 1019 |
|
| 1020 |
/** |
| 1021 |
* Render the product button for every product in shop page |
| 1022 |
*/ |
| 1023 |
public function render_product_item_listing_button() |
| 1024 |
{ |
| 1025 |
global $product; |
| 1026 |
$prefix = isset($this->options['prefix']) ? $this->options['prefix'] : ''; |
| 1027 |
$phone = $prefix . $this->options['telephone']; |
| 1028 |
$cta = __("Request support on WhatsApp", "spoki"); |
| 1029 |
if (isset($this->options['woocommerce']['product_item_listing_button_cta']) && !empty($this->options['woocommerce']['product_item_listing_button_cta'])) { |
| 1030 |
$cta = $this->options['woocommerce']['product_item_listing_button_cta']; |
| 1031 |
} |
| 1032 |
$message = __("Hi, I want to buy:", "spoki"); |
| 1033 |
if (isset($this->options['woocommerce']['product_item_listing_button_text']) && !empty($this->options['woocommerce']['product_item_listing_button_text'])) { |
| 1034 |
$message = $this->options['woocommerce']['product_item_listing_button_text']; |
| 1035 |
} |
| 1036 |
$color = isset($this->options['woocommerce']['product_item_listing_button_color']) ? $this->options['woocommerce']['product_item_listing_button_color'] : '#23D366'; |
| 1037 |
$margin_top = isset($this->options['woocommerce']['product_item_listing_button_margin_top']) ? $this->options['woocommerce']['product_item_listing_button_margin_top'] : '4'; |
| 1038 |
$margin_bottom = isset($this->options['woocommerce']['product_item_listing_button_margin_bottom']) ? $this->options['woocommerce']['product_item_listing_button_margin_bottom'] : '4'; |
| 1039 |
$margin_left = isset($this->options['woocommerce']['product_item_listing_button_margin_left']) ? $this->options['woocommerce']['product_item_listing_button_margin_left'] : '0'; |
| 1040 |
$margin_right = isset($this->options['woocommerce']['product_item_listing_button_margin_right']) ? $this->options['woocommerce']['product_item_listing_button_margin_right'] : '0'; |
| 1041 |
$font_size = isset($this->options['woocommerce']['product_item_listing_button_font_size']) ? $this->options['woocommerce']['product_item_listing_button_font_size'] : '12'; |
| 1042 |
$border_type = isset($this->options['woocommerce']['product_item_listing_button_border']) ? $this->options['woocommerce']['product_item_listing_button_border'] : 'rounded'; |
| 1043 |
|
| 1044 |
$this->render_product_button($product, $phone, $cta, $message, $color, $border_type, $margin_top, $margin_bottom, $margin_left, $margin_right, $font_size, true); |
| 1045 |
} |
| 1046 |
|
| 1047 |
/** |
| 1048 |
* Render the button in the cart page |
| 1049 |
*/ |
| 1050 |
public function render_cart_button() |
| 1051 |
{ |
| 1052 |
global $product; |
| 1053 |
$prefix = isset($this->options['prefix']) ? $this->options['prefix'] : ''; |
| 1054 |
$phone = $prefix . $this->options['telephone']; |
| 1055 |
$cta = __("Order via WhatsApp", "spoki"); |
| 1056 |
if (isset($this->options['woocommerce']['cart_button_cta']) && !empty($this->options['woocommerce']['cart_button_cta'])) { |
| 1057 |
$cta = $this->options['woocommerce']['cart_button_cta']; |
| 1058 |
} |
| 1059 |
$message = __("Hi, I want to buy:", "spoki"); |
| 1060 |
if (isset($this->options['woocommerce']['cart_button_text']) && !empty($this->options['woocommerce']['cart_button_text'])) { |
| 1061 |
$message = $this->options['woocommerce']['cart_button_text']; |
| 1062 |
} |
| 1063 |
$color = isset($this->options['woocommerce']['cart_button_color']) ? $this->options['woocommerce']['cart_button_color'] : '#23D366'; |
| 1064 |
$margin_top = isset($this->options['woocommerce']['cart_button_margin_top']) ? $this->options['woocommerce']['cart_button_margin_top'] : '4'; |
| 1065 |
$margin_bottom = isset($this->options['woocommerce']['cart_button_margin_bottom']) ? $this->options['woocommerce']['cart_button_margin_bottom'] : '4'; |
| 1066 |
$margin_left = isset($this->options['woocommerce']['cart_button_margin_left']) ? $this->options['woocommerce']['cart_button_margin_left'] : '0'; |
| 1067 |
$margin_right = isset($this->options['woocommerce']['cart_button_margin_right']) ? $this->options['woocommerce']['cart_button_margin_right'] : '0'; |
| 1068 |
$font_size = isset($this->options['woocommerce']['cart_button_font_size']) ? $this->options['woocommerce']['cart_button_font_size'] : '12'; |
| 1069 |
$icon_size = intval($font_size) < 16 ? 16 : $font_size; |
| 1070 |
$final_message = urlencode($message); |
| 1071 |
|
| 1072 |
$products = WC()->cart->get_cart(); |
| 1073 |
|
| 1074 |
foreach ($products as $item) { |
| 1075 |
$product_id = $item['product_id']; |
| 1076 |
$qty = $item['quantity']; |
| 1077 |
$product = wc_get_product($product_id); |
| 1078 |
$product_url = $product->get_permalink(); |
| 1079 |
$product_title = $product->get_name(); |
| 1080 |
$price = wp_strip_all_tags(wc_price(wc_get_price_including_tax($product), ['currency' => 'EUR'])); |
| 1081 |
$encoded_title = urlencode($product_title); |
| 1082 |
$encoded_product_url = urlencode($product_url); |
| 1083 |
$final_message .= "%0D%0A%0D%0A(ID:%20$product_id)%20*$encoded_title*%20$price%20x$qty%0D%0A$encoded_product_url"; |
| 1084 |
} |
| 1085 |
$furl = get_bloginfo('url'); |
| 1086 |
$href = SPOKI_BASE_API_BUTTONS . "?type=4&phone=$phone&text=$final_message&furl=$furl"; |
| 1087 |
$title = "$cta"; |
| 1088 |
$class = 'button spoki-button size-4'; |
| 1089 |
$border_type = isset($this->options['woocommerce']['cart_button_border']) ? $this->options['woocommerce']['cart_button_border'] : 'rounded'; |
| 1090 |
|
| 1091 |
$border_radius = '16px'; |
| 1092 |
if ($border_type == 'squared') { |
| 1093 |
$border_radius = '0'; |
| 1094 |
} |
| 1095 |
|
| 1096 |
echo "<div class='spoki-shadowed-button'><div class='spoki-button-relative' style='margin-top:{$margin_top}px;margin-bottom:{$margin_bottom}px;margin-left:{$margin_left}px;margin-right:{$margin_right}px;'><a href='$href' target='_blank' rel='nofollow' title='$title' class='$class' style='background-color:$color;border-radius:$border_radius;font-size:{$font_size}px'>" . spoki_get_wa_logo($icon_size) . "<span>$cta</span></a></div></div>"; |
| 1097 |
} |
| 1098 |
|
| 1099 |
/** |
| 1100 |
* Render the button in the product page |
| 1101 |
*/ |
| 1102 |
public function render_single_product_button() |
| 1103 |
{ |
| 1104 |
global $product; |
| 1105 |
$prefix = isset($this->options['prefix']) ? $this->options['prefix'] : ''; |
| 1106 |
$phone = $prefix . $this->options['telephone']; |
| 1107 |
$cta = __("Request support on WhatsApp", "spoki"); |
| 1108 |
if (isset($this->options['woocommerce']['single_product_button_cta']) && !empty($this->options['woocommerce']['single_product_button_cta'])) { |
| 1109 |
$cta = $this->options['woocommerce']['single_product_button_cta']; |
| 1110 |
} |
| 1111 |
$message = __("Hi, I want to buy:", "spoki"); |
| 1112 |
if (isset($this->options['woocommerce']['single_product_button_text']) && !empty($this->options['woocommerce']['single_product_button_text'])) { |
| 1113 |
$message = $this->options['woocommerce']['single_product_button_text']; |
| 1114 |
} |
| 1115 |
$position = isset($this->options['woocommerce']['single_product_button_position']) ? $this->options['woocommerce']['single_product_button_position'] : 'after_atc'; |
| 1116 |
$color = isset($this->options['woocommerce']['single_product_button_color']) ? $this->options['woocommerce']['single_product_button_color'] : '#23D366'; |
| 1117 |
$margin_top = isset($this->options['woocommerce']['single_product_button_margin_top']) ? $this->options['woocommerce']['single_product_button_margin_top'] : '4'; |
| 1118 |
$margin_bottom = isset($this->options['woocommerce']['single_product_button_margin_bottom']) ? $this->options['woocommerce']['single_product_button_margin_bottom'] : '4'; |
| 1119 |
$margin_left = isset($this->options['woocommerce']['single_product_button_margin_left']) ? $this->options['woocommerce']['single_product_button_margin_left'] : '0'; |
| 1120 |
$margin_right = isset($this->options['woocommerce']['single_product_button_margin_right']) ? $this->options['woocommerce']['single_product_button_margin_right'] : '0'; |
| 1121 |
$font_size = isset($this->options['woocommerce']['single_product_button_font_size']) ? $this->options['woocommerce']['single_product_button_font_size'] : '12'; |
| 1122 |
$border_type = isset($this->options['woocommerce']['single_product_button_border']) ? $this->options['woocommerce']['single_product_button_border'] : 'rounded'; |
| 1123 |
|
| 1124 |
$this->render_product_button($product, $phone, $cta, $message, $color, $border_type, $margin_top, $margin_bottom, $margin_left, $margin_right, $font_size, false, $position); |
| 1125 |
} |
| 1126 |
|
| 1127 |
/** |
| 1128 |
* Render the button of a product |
| 1129 |
* |
| 1130 |
* @param $product |
| 1131 |
* @param $phone |
| 1132 |
* @param $cta |
| 1133 |
* @param $message |
| 1134 |
* @param null $position |
| 1135 |
*/ |
| 1136 |
public function render_product_button($product, $phone, $cta, $message, $color = '#23D366', $border_type = 'rounded', $margin_top = '4', $margin_bottom = '4', $margin_left = '0', $margin_right = '0', $font_size = '12', $is_listing = false, $position = null) |
| 1137 |
{ |
| 1138 |
$product_url = $product->get_permalink(); |
| 1139 |
$product_title = $product->get_name(); |
| 1140 |
$product_id = $product->get_id(); |
| 1141 |
$price = wp_strip_all_tags(wc_price(wc_get_price_including_tax($product), ['currency' => 'EUR'])); |
| 1142 |
$encoded_message = urlencode($message); |
| 1143 |
$encoded_title = urlencode($product_title); |
| 1144 |
$encoded_product_url = urlencode($product_url); |
| 1145 |
$final_message = "$encoded_message%0D%0A%0D%0A(ID:%20$product_id)%20*$encoded_title*%20$price%0D%0A$encoded_product_url"; |
| 1146 |
$type = $is_listing ? '2' : '3'; |
| 1147 |
$title = "$cta $product_title"; |
| 1148 |
$additional_class = sprintf('product_type_%s', $product->get_type()); |
| 1149 |
|
| 1150 |
$this->render_relative_button($phone, $cta, $title, $final_message, $additional_class, $type, $color, $border_type, $margin_top, $margin_bottom, $margin_left, $margin_right, $font_size, $position); |
| 1151 |
} |
| 1152 |
|
| 1153 |
/** |
| 1154 |
* Render a relative button |
| 1155 |
*/ |
| 1156 |
public function render_relative_button($phone, $cta, $title, $final_message, $additional_class, $type, $color = '#23D366', $border_type = 'rounded', $margin_top = '4', $margin_bottom = '4', $margin_left = '0', $margin_right = '0', $font_size = '12', $position = null) |
| 1157 |
{ |
| 1158 |
$class = sprintf('button spoki-button %s', $additional_class); |
| 1159 |
if (isset($position)) { |
| 1160 |
$class .= " size-2 $position"; |
| 1161 |
} else { |
| 1162 |
$class .= " size-4"; |
| 1163 |
} |
| 1164 |
|
| 1165 |
$border_radius = '16px'; |
| 1166 |
if ($border_type == 'squared') { |
| 1167 |
$border_radius = '0'; |
| 1168 |
} |
| 1169 |
|
| 1170 |
$furl = get_bloginfo('url'); |
| 1171 |
$href = SPOKI_BASE_API_BUTTONS . "?type={$type}&phone=$phone&text=$final_message&furl=$furl"; |
| 1172 |
$icon_size = intval($font_size) < 16 ? 16 : $font_size; |
| 1173 |
|
| 1174 |
echo "<div class='spoki-shadowed-button'><div class='spoki-button-relative' style='margin-top:{$margin_top}px;margin-bottom:{$margin_bottom}px;margin-left:{$margin_left}px;margin-right:{$margin_right}px;'><a href='$href' target='_blank' rel='nofollow' title='$title' class='$class' style='background-color:$color;border-radius:$border_radius;font-size:{$font_size}px'>" . spoki_get_wa_logo($icon_size) . "<span>$cta</span></a></div></div>"; |
| 1175 |
} |
| 1176 |
|
| 1177 |
/** |
| 1178 |
* Get the link to change plan |
| 1179 |
* |
| 1180 |
* @param $is_upgrade |
| 1181 |
* @return string |
| 1182 |
*/ |
| 1183 |
public function get_plan_link($is_upgrade): string |
| 1184 |
{ |
| 1185 |
$url = $this->shop['language'] == 'it-IT' ? 'https://spoki.it/spoki-flex-acquista-pacchetti-flex/?' : 'https://spoki.it/spoki-flex-acquista-pacchetti-flex/spoki-flex-packages/?'; |
| 1186 |
|
| 1187 |
if ($this->options['account_info']['upgrade_url'] ?? '') { |
| 1188 |
$url = $this->options['account_info']['upgrade_url']; |
| 1189 |
} |
| 1190 |
if ($is_upgrade) { |
| 1191 |
$url .= '&is_upgrade=true'; |
| 1192 |
} |
| 1193 |
return $url; |
| 1194 |
} |
| 1195 |
|
| 1196 |
/** |
| 1197 |
* Get the link to change plan to pro |
| 1198 |
* |
| 1199 |
* @return string |
| 1200 |
*/ |
| 1201 |
public function get_pro_plan_link(): string |
| 1202 |
{ |
| 1203 |
return 'https://spoki.it/piani-e-prezzi-spoki-pro/?'; |
| 1204 |
} |
| 1205 |
|
| 1206 |
/** |
| 1207 |
* Update Spoki options |
| 1208 |
* |
| 1209 |
* @param $current_options |
| 1210 |
* @param $new_options |
| 1211 |
*/ |
| 1212 |
private function update_options($current_options, $new_options) |
| 1213 |
{ |
| 1214 |
$c_options = is_string($current_options) ? [] : $current_options; |
| 1215 |
if (isset($new_options["woocommerce"])) { |
| 1216 |
$woocommerce = []; |
| 1217 |
if (isset($c_options["abandoned_carts"])) { |
| 1218 |
$woocommerce = array_merge($c_options["woocommerce"], $new_options["woocommerce"]); |
| 1219 |
} else { |
| 1220 |
$woocommerce = $new_options["woocommerce"]; |
| 1221 |
} |
| 1222 |
$new_options["woocommerce"] = $woocommerce; |
| 1223 |
} |
| 1224 |
if (isset($new_options["abandoned_carts"])) { |
| 1225 |
$abandoned_carts = []; |
| 1226 |
if (isset($c_options["abandoned_carts"])) { |
| 1227 |
$abandoned_carts = array_merge($c_options["abandoned_carts"], $new_options["abandoned_carts"]); |
| 1228 |
} else { |
| 1229 |
$abandoned_carts = $new_options["abandoned_carts"]; |
| 1230 |
} |
| 1231 |
$new_options["abandoned_carts"] = $abandoned_carts; |
| 1232 |
} |
| 1233 |
if (isset($new_options["secret_status"])) { |
| 1234 |
$secret_status = []; |
| 1235 |
if (isset($c_options["secret_status"])) { |
| 1236 |
$secret_status = array_merge($c_options["secret_status"], $new_options["secret_status"]); |
| 1237 |
} else { |
| 1238 |
$secret_status = $new_options["secret_status"]; |
| 1239 |
} |
| 1240 |
$new_options["secret_status"] = $secret_status; |
| 1241 |
} |
| 1242 |
if (isset($new_options["account_info"])) { |
| 1243 |
$account_info = []; |
| 1244 |
if (isset($c_options["account_info"])) { |
| 1245 |
$account_info = array_merge($c_options["account_info"], $new_options["account_info"]); |
| 1246 |
} else { |
| 1247 |
$account_info = $new_options["account_info"]; |
| 1248 |
} |
| 1249 |
$new_options["account_info"] = $account_info; |
| 1250 |
} |
| 1251 |
update_option(SPOKI_OPTIONS, array_merge($c_options, $new_options)); |
| 1252 |
$this->options = get_option(SPOKI_OPTIONS); |
| 1253 |
} |
| 1254 |
|
| 1255 |
/** |
| 1256 |
* Check the secret status periodically |
| 1257 |
*/ |
| 1258 |
public function check_secret_status() |
| 1259 |
{ |
| 1260 |
$this->fetch_secret_status(true); |
| 1261 |
} |
| 1262 |
|
| 1263 |
/** |
| 1264 |
* Fetch the status of the Spoki keys |
| 1265 |
*/ |
| 1266 |
public function fetch_secret_status($force_checking = false) |
| 1267 |
{ |
| 1268 |
$response = null; |
| 1269 |
if ($force_checking) { |
| 1270 |
$response = $this->check_spoki_status(); |
| 1271 |
} |
| 1272 |
|
| 1273 |
if (!isset($this->options['secret']) || $this->options['secret'] == '' || !isset($this->options['delivery_url']) || $this->options['delivery_url'] == '') { |
| 1274 |
$this->update_options(get_option(SPOKI_OPTIONS), ["secret_status" => [ |
| 1275 |
'secret' => isset($this->options['secret']) ? $this->options['secret'] : '', |
| 1276 |
'delivery_url' => isset($this->options['delivery_url']) ? $this->options['delivery_url'] : '', |
| 1277 |
'code' => 0, |
| 1278 |
'message' => '' |
| 1279 |
]]); |
| 1280 |
} else if (!isset($this->options['secret_status']) || $this->options['secret_status']['code'] != 200 || $this->options['secret'] != $this->options['secret_status']['secret'] || $this->options['delivery_url'] != $this->options['secret_status']['delivery_url']) { |
| 1281 |
if (!$force_checking) { |
| 1282 |
$response = $this->check_spoki_status(); |
| 1283 |
} |
| 1284 |
$this->update_options(get_option(SPOKI_OPTIONS), ["secret_status" => [ |
| 1285 |
'secret' => isset($this->options['secret']) ? $this->options['secret'] : '', |
| 1286 |
'delivery_url' => isset($this->options['delivery_url']) ? $this->options['delivery_url'] : '', |
| 1287 |
'code' => wp_remote_retrieve_response_code($response), |
| 1288 |
'message' => wp_remote_retrieve_response_message($response) |
| 1289 |
]]); |
| 1290 |
} |
| 1291 |
} |
| 1292 |
|
| 1293 |
/** |
| 1294 |
* Activation Reset |
| 1295 |
*/ |
| 1296 |
public function activation_reset() |
| 1297 |
{ |
| 1298 |
register_uninstall_hook(SPOKI_PLUGIN_FILE, array($this, 'uninstall_plugin')); |
| 1299 |
if (!class_exists('WooCommerce')) { |
| 1300 |
return; |
| 1301 |
} |
| 1302 |
$this->initialize_cart_abandonment_tables(); |
| 1303 |
$Abandonment = Spoki_Abandoned_Carts::instance(); |
| 1304 |
$spokiDomain = $Abandonment->get_spoki_setting_by_meta("spoki_domain"); |
| 1305 |
$Abandonment->set_spoki_setting_by_meta("plugin_activated", "true"); |
| 1306 |
if ($spokiDomain != null || $spokiDomain != "") |
| 1307 |
$Abandonment->save_webhook_url($spokiDomain); |
| 1308 |
} |
| 1309 |
|
| 1310 |
/** |
| 1311 |
* Deactivation Reset |
| 1312 |
*/ |
| 1313 |
public function deactivation_reset() |
| 1314 |
{ |
| 1315 |
$Abandonment = Spoki_Abandoned_Carts::instance(); |
| 1316 |
# Unschedule hook for versions <= v2.8.1 |
| 1317 |
$Abandonment->unschedule_hook(); |
| 1318 |
if (!class_exists('WooCommerce')) { |
| 1319 |
return; |
| 1320 |
} |
| 1321 |
$spokiDomain = $Abandonment->get_spoki_setting_by_meta("spoki_domain"); |
| 1322 |
$Abandonment->set_spoki_setting_by_meta("plugin_activated", "false"); |
| 1323 |
if ($spokiDomain != null || $spokiDomain != "") |
| 1324 |
$Abandonment->disable_webhook_url($spokiDomain); |
| 1325 |
} |
| 1326 |
|
| 1327 |
/** |
| 1328 |
* Uninstall Plugin |
| 1329 |
*/ |
| 1330 |
public function uninstall_plugin() |
| 1331 |
{ |
| 1332 |
if (!class_exists('WooCommerce')) { |
| 1333 |
return; |
| 1334 |
} |
| 1335 |
$Abandonment = Spoki_Abandoned_Carts::instance(); |
| 1336 |
$spokiDomain = $Abandonment->get_spoki_setting_by_meta("spoki_domain"); |
| 1337 |
$Abandonment->set_spoki_setting_by_meta("plugin_activated", "false"); |
| 1338 |
if ($spokiDomain != null || $spokiDomain != "") |
| 1339 |
$Abandonment->disable_webhook_url($spokiDomain); |
| 1340 |
} |
| 1341 |
} |
| 1342 |
|
| 1343 |
/** |
| 1344 |
* Executed on activation of the plugin. |
| 1345 |
* Redirects the user after plugin activation. |
| 1346 |
*/ |
| 1347 |
function spoki_activation() |
| 1348 |
{ |
| 1349 |
if (!((isset($_REQUEST['action']) && 'activate-selected' === $_REQUEST['action']) && (isset($_POST['checked']) && count($_POST['checked']) > 1))) { |
| 1350 |
add_option('spoki_activation_redirect', true); |
| 1351 |
} |
| 1352 |
} |
| 1353 |
|
| 1354 |
/** |
| 1355 |
* Redirects the user after plugin activation. |
| 1356 |
*/ |
| 1357 |
function spoki_activation_redirect() |
| 1358 |
{ |
| 1359 |
if (get_option('spoki_activation_redirect', false)) { |
| 1360 |
delete_option('spoki_activation_redirect'); |
| 1361 |
exit(wp_redirect(admin_url('/admin.php?page=' . SPOKI_PLUGIN_NAME))); |
| 1362 |
} |
| 1363 |
} |
| 1364 |
|
| 1365 |
/** |
| 1366 |
* Executed on deactivation of the plugin |
| 1367 |
*/ |
| 1368 |
function spoki_deactivation() |
| 1369 |
{ |
| 1370 |
// delete_option(SPOKI_OPTIONS); |
| 1371 |
$timestamp = wp_next_scheduled('spoki_cron_hook'); |
| 1372 |
wp_unschedule_event($timestamp, 'spoki_cron_hook'); |
| 1373 |
} |
| 1374 |
|
| 1375 |
register_deactivation_hook(__FILE__, 'spoki_deactivation'); |
| 1376 |
register_activation_hook(__FILE__, 'spoki_activation'); |
| 1377 |
add_action('admin_init', 'spoki_activation_redirect'); |
| 1378 |
|