PluginProbe
WANotifier for Forms and Actions / 3.0.1
WANotifier for Forms and Actions v3.0.1
3.1.0 3.0.4 2.7.10 2.7.11 2.7.12 2.7.13 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 3.0.0 3.0.1 3.0.2 3.0.3 trunk 0.1.0 0.1.1 1.0.0 1.0.1 1.0.2 1.0.3 All 66 releases
notifier / includes / class-notifier.php

class-notifier.php in WANotifier for Forms and Actions 3.0.1, at includes/class-notifier.php

522 lines 16.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit;
4 }
5
6 /**
7 * The core plugin class.
8 *
9 * @package Notifier
10 */
11 class Notifier {
12 /**
13 * The single instance of the class.
14 */
15 protected static $_instance = null;
16
17 /**
18 * Notifier Constructor.
19 */
20 public function __construct() {
21 $this->define_constants();
22 $this->includes();
23 $this->init_hooks();
24 }
25
26 /**
27 * Define Constants.
28 */
29 private function define_constants() {
30 $this->define( 'NOTIFIER_VERSION', '3.0.1' );
31 $this->define( 'NOTIFIER_NAME', 'notifier' );
32 $this->define( 'NOTIFIER_PREFIX', 'notifier_' );
33 $this->define( 'NOTIFIER_URL', trailingslashit( plugins_url( '', dirname(__FILE__) ) ) );
34 $this->define( 'NOTIFIER_APP_BASE_URL', 'https://app.wanotifier.com' );
35 $this->define( 'NOTIFIER_APP_API_PATH', 'api/v1' );
36 $this->define( 'NOTIFIER_ACTIVITY_TABLE_NAME', 'notifier_activity_log' );
37 $this->define( 'NOTIFIER_CART_ABANDONMENT_TABLE', 'notifier_cart_abandonment' );
38 }
39
40 /**
41 * Define constant if not already set.
42 *
43 * @param string $name Constant name.
44 * @param string|bool $value Constant value.
45 */
46 private function define( $name, $value ) {
47 if ( ! defined( $name ) ) {
48 define( $name, $value );
49 }
50 }
51
52 /**
53 * Main Notifier Instance.
54 *
55 * @return Notifier instance.
56 */
57 public static function get_instance() {
58 if ( is_null( self::$_instance ) ) {
59 self::$_instance = new self();
60 }
61 return self::$_instance;
62 }
63
64 /**
65 * Include required core files used in admin and on the frontend.
66 */
67 private function includes() {
68 // Functions
69 require_once NOTIFIER_PATH . 'includes/functions/functions-notifier-helpers.php';
70 require_once NOTIFIER_PATH . 'libraries/action-scheduler/action-scheduler.php';
71
72 // Classes
73 require_once NOTIFIER_PATH . 'includes/classes/class-notifier-admin-notices.php';
74 require_once NOTIFIER_PATH . 'includes/classes/class-notifier-connection.php';
75 require_once NOTIFIER_PATH . 'includes/classes/class-notifier-migration.php';
76 require_once NOTIFIER_PATH . 'includes/classes/class-notifier-backend.php';
77 require_once NOTIFIER_PATH . 'includes/classes/class-notifier-notification-merge-tags.php';
78 require_once NOTIFIER_PATH . 'includes/classes/class-notifier-notification-triggers.php';
79 require_once NOTIFIER_PATH . 'includes/classes/class-notifier-frontend.php';
80 }
81
82 /**
83 * Hook into actions and filters.
84 */
85 private function init_hooks() {
86 register_activation_hook ( NOTIFIER_FILE, array( $this, 'activate') );
87 register_deactivation_hook ( NOTIFIER_FILE, array( $this, 'deactivate') );
88
89 add_action( 'after_setup_theme', array( 'Notifier_Admin_Notices', 'init' ) );
90 add_action( 'after_setup_theme', array( 'Notifier_Connection', 'init' ) );
91 add_action( 'after_setup_theme', array( 'Notifier_Migration', 'init' ) );
92 add_action( 'after_setup_theme', array( 'Notifier_Backend', 'init' ) );
93 add_action( 'after_setup_theme', array( 'Notifier_Notification_Merge_Tags', 'init' ) );
94 add_action( 'after_setup_theme', array( 'Notifier_Notification_Triggers', 'init' ) );
95 add_action( 'after_setup_theme', array( 'Notifier_Frontend', 'init' ) );
96 add_action( 'admin_enqueue_scripts', array( $this , 'admin_scripts') );
97 add_action( 'wp_enqueue_scripts', array( $this , 'frontend_scripts') );
98 add_action( 'in_admin_header', array( $this , 'embed_page_header' ) );
99
100 add_action( 'after_setup_theme', array( $this, 'maybe_include_integrations' ) );
101
102 add_action( 'init', array( $this, 'load_textdomain' ) );
103 add_action( 'wp_loaded', array( $this, 'setup_activity_log' ) );
104 add_action( 'notifier_clean_old_logs', array( $this, 'notifier_delete_old_activity_logs' ) );
105
106 add_action( 'wp_loaded', array( $this, 'create_cart_abandonment_table' ) );
107 }
108
109 /**
110 * Load plugin text domain for translations.
111 */
112 public function load_textdomain() {
113 load_plugin_textdomain( 'notifier', false, dirname( plugin_basename( NOTIFIER_FILE ) ) . '/languages' );
114 }
115
116 /**
117 * Setup during plugin activation
118 */
119 public function activate() {
120 $notifier_plugin_data = get_option('notifier_meta', array());
121 if (isset($notifier_plugin_data['as_clear_log']) && $notifier_plugin_data['as_clear_log'] === 'yes') {
122 unset($notifier_plugin_data['as_clear_log']);
123 update_option('notifier_meta', $notifier_plugin_data);
124 }
125 }
126
127 /**
128 * Setup during plugin deactivation
129 */
130 public function deactivate() {
131 as_unschedule_action('notifier_check_cart_abandonment');
132 as_unschedule_action('notifier_clean_old_logs');
133 $notifier_plugin_data = get_option('notifier_meta', array());
134 $notifier_plugin_data['as_clear_log'] = 'yes';
135 update_option('notifier_meta', $notifier_plugin_data);
136 }
137
138 /**
139 * Check if the plugin was updated and run the upgrade routine if necessary.
140 */
141 public function setup_activity_log() {
142 $notifier_plugin_data = get_option('notifier_meta', array());
143 if ( ! isset( $notifier_plugin_data['activity_log_table'] ) || $notifier_plugin_data['activity_log_table'] !== 'yes' ) {
144 self::create_notifier_activity_log_table();
145 }
146
147 $args = array();
148 $as_clear_log = isset($notifier_plugin_data['as_clear_log']) ? $notifier_plugin_data['as_clear_log'] : 'no';
149 if ($as_clear_log !== 'yes') {
150 if (false === as_next_scheduled_action('notifier_clean_old_logs')) {
151 as_schedule_recurring_action(time(), DAY_IN_SECONDS, 'notifier_clean_old_logs', $args);
152 }
153 }
154 }
155
156 /**
157 * Check if plugin's page
158 */
159 public static function is_notifier_page() {
160 $current_screen = get_current_screen();
161 if ( strpos( $current_screen->id, NOTIFIER_NAME ) !== false
162 && strpos( $current_screen->id, 'order-notifications-for-woocommerce' ) === false
163 ) {
164 return true;
165 }
166
167 return false;
168 }
169
170 /**
171 * Add admin scripts and styles
172 */
173 public function admin_scripts () {
174 if ( ! Notifier_Migration::is_migration_complete() && 'dismissed' !== get_option( 'notifier_migration_notice_dismissed' ) ) {
175 wp_enqueue_script(
176 'notifier-admin',
177 NOTIFIER_URL . 'assets/js/admin.js',
178 array( 'jquery' ),
179 NOTIFIER_VERSION,
180 true
181 );
182 wp_localize_script( 'notifier-admin', 'notifier_migration', array(
183 'ajax_url' => admin_url( 'admin-ajax.php' ),
184 'nonce' => wp_create_nonce( 'notifier_dismiss_migration' ),
185 ) );
186 }
187
188 if (!self::is_notifier_page()) {
189 return;
190 }
191
192 wp_enqueue_script(
193 NOTIFIER_NAME . '-admin-react',
194 NOTIFIER_URL . 'assets/js/admin-react.js',
195 array(),
196 NOTIFIER_VERSION,
197 true
198 );
199
200 wp_enqueue_style(
201 NOTIFIER_NAME . '-admin-css',
202 NOTIFIER_URL . 'assets/css/admin.css',
203 null,
204 NOTIFIER_VERSION
205 );
206 }
207
208 /**
209 * Add frontend scripts and styles
210 */
211 public function frontend_scripts () {
212 if('yes' === get_option('notifier_ctc_enable')){
213 // Styles
214 wp_enqueue_style(
215 NOTIFIER_NAME . '-frontend-css',
216 NOTIFIER_URL . 'assets/css/frontend.css',
217 null,
218 NOTIFIER_VERSION
219 );
220 }
221
222 if ( ! self::is_woo_handled_by_standalone_plugin() && 'yes' === get_option('notifier_enable_abandonment_cart_tracking', 'no') && class_exists('WooCommerce') && is_checkout() ) {
223 wp_enqueue_script(
224 NOTIFIER_NAME . '-js',
225 NOTIFIER_URL . 'assets/js/script.js',
226 array('jquery'),
227 NOTIFIER_VERSION,
228 true
229 );
230
231 wp_localize_script(
232 NOTIFIER_NAME . '-js',
233 'notifierFrontObj',
234 array(
235 'ajaxurl' => admin_url( 'admin-ajax.php' ),
236 'security' => wp_create_nonce('notifier_save_cart_abandonment_data'),
237 )
238 );
239 }
240 }
241
242 /**
243 * Set up a div for the header embed to render into.
244 * Only renders for legacy (non-SPA) pages like the trigger CPT editor.
245 * SPA pages render the header via the React app.
246 */
247 public static function embed_page_header() {
248 if (!self::is_notifier_page()) {
249 return;
250 }
251
252 $screen = get_current_screen();
253 $spa_pages = array(
254 'toplevel_page_notifier',
255 'wanotifier_page_notifier-chat-button',
256 'wanotifier_page_notifier-settings',
257 'wanotifier_page_notifier-logs',
258 'wanotifier_page_notifier-migration',
259 );
260
261 if ( in_array( $screen->id, $spa_pages, true ) ) {
262 return;
263 }
264
265 $cpt = ( '' !== $screen->post_type ) ? $screen->post_type : '';
266 ?>
267 <div id="notifier-admin-header" data-post-type="<?php echo esc_attr($cpt); ?>">
268 <div class="notifier-admin-header-content">
269 <div class="header-page-title w-30 d-flex align-content-center">
270 <a class="header-logo" href="admin.php?page=notifier"><img src="<?php echo esc_url( NOTIFIER_URL . 'assets/images/favicon.svg' ); ?>"></a>
271 <h2>WANotifier</h2>
272 </div>
273 <div class="header-action-links w-30 d-flex justify-content-end">
274 <span class="review-us-link">Review us: <a href="https://wordpress.org/support/plugin/notifier/reviews/#new-post" target="_blank">⭐⭐⭐⭐⭐</a></span>
275 <span class="header-version">Version: <?php echo esc_html(NOTIFIER_VERSION); ?></span>
276 <a href="https://wanotifier.com/support/" target="_blank">Help</a>
277 </div>
278 </div>
279 </div>
280 <?php
281 }
282
283 /**
284 * For sending API requests
285 */
286 public static function send_api_request ( $endpoint, $args, $method = 'POST', $headers = array() ) {
287 $api_key = get_option('notifier_api_key');
288 $api_key = trim($api_key);
289 if('' == $api_key) {
290 return false;
291 }
292
293 if(empty($headers)){
294 $headers = array(
295 'Content-Type' => 'application/json; charset=utf-8'
296 );
297 }
298
299 $request_url = NOTIFIER_APP_BASE_URL . '/' . NOTIFIER_APP_API_PATH . '/' . $endpoint . '?key=' . esc_attr($api_key);
300 $request_args = array(
301 'method' => $method,
302 'headers' => $headers,
303 'timeout' => 120,
304 'body' => json_encode($args),
305 'sslverify' => true
306 );
307
308 $response = wp_remote_request( $request_url, $request_args );
309
310 $response_body = wp_remote_retrieve_body( $response );
311
312 if ( is_wp_error( $response ) ) {
313 error_log( $response->get_error_message() );
314 return false;
315 } else {
316 $response_body = wp_remote_retrieve_body( $response );
317 return json_decode($response_body);
318 }
319 }
320
321 /**
322 * Whether the standalone WANotifier for WooCommerce plugin is active and
323 * has completed its connection/migration, meaning this plugin should defer
324 * all Woo/WCAR functionality to it.
325 *
326 * @return bool
327 */
328 public static function is_woo_handled_by_standalone_plugin() {
329 static $result = null;
330 if ( null !== $result ) {
331 return $result;
332 }
333
334 if ( ! function_exists( 'is_plugin_active' ) ) {
335 require_once ABSPATH . 'wp-admin/includes/plugin.php';
336 }
337
338 if ( ! is_plugin_active( 'order-notifications-for-woocommerce/order-notifications-for-woocommerce.php' ) ) {
339 $result = false;
340 return false;
341 }
342
343 if ( 'complete' === get_option( 'wanowc_migration_status' ) ) {
344 $result = true;
345 return true;
346 }
347
348 if ( get_option( 'wanowc_conn_woocommerce_auth_key' ) || get_option( 'wanowc_conn_wcar_auth_key' ) ) {
349 $result = true;
350 return true;
351 }
352
353 $result = false;
354 return false;
355 }
356
357 /**
358 * Load Woocommerce class if it's present is activated
359 */
360 public static function maybe_include_integrations () {
361 $woo_handled = self::is_woo_handled_by_standalone_plugin();
362
363 // Woocommerce — skip when the standalone plugin handles it
364 if ( ! $woo_handled && class_exists( 'WooCommerce' ) ) {
365 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-woocommerce.php';
366 Notifier_Woocommerce::init();
367 }
368 if ( ! $woo_handled && ! class_exists( 'WC_Session' ) && class_exists( 'WooCommerce' ) ) {
369 include_once( WP_PLUGIN_DIR . '/woocommerce/includes/abstracts/abstract-wc-session.php' );
370 }
371
372 // WooCommerce Cart Abandonment Recovery — skip when the standalone plugin handles it
373 if ( ! $woo_handled && class_exists( 'CARTFLOWS_CA_Loader' ) && defined('CARTFLOWS_CA_VER') && version_compare(CARTFLOWS_CA_VER, '1.2.25', '>=')) {
374 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-wcar.php';
375 Notifier_WCAR::init();
376 }
377
378 // Gravity Forms
379 if ( class_exists( 'GFCommon' ) ) {
380 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-gravityforms.php';
381 Notifier_GravityForms::init();
382 }
383
384 // Contact Form 7
385 if ( class_exists( 'WPCF7' ) ) {
386 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-cf7.php';
387 Notifier_ContactForm7::init();
388 }
389
390 // WPForms
391 if ( class_exists( 'WPForms' ) ) {
392 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-wpforms.php';
393 Notifier_WPForms::init();
394 }
395
396 // Ninja Forms
397 if ( class_exists( 'Ninja_Forms' ) ) {
398 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-ninjaforms.php';
399 Notifier_NinjaForms::init();
400 }
401
402 //FrmForm
403 if ( class_exists( 'FrmForm' ) ) {
404 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-formidable.php';
405 Notifier_Formidable::init();
406 }
407
408 //WPFluentForm
409 if ( function_exists( 'fluentFormApi' ) ) {
410 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-fluentforms.php';
411 Notifier_FluentForms::init();
412 }
413
414 //Forminator
415 if ( class_exists( 'Forminator' ) ) {
416 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-forminator.php';
417 Notifier_Forminator::init();
418 }
419
420 //SureForms
421 if ( class_exists( 'SRFM\Plugin_Loader' ) ) {
422 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-sureforms.php';
423 Notifier_SureForms::init();
424 }
425
426 //WS Form
427 if ( class_exists( 'WS_Form' ) ) {
428 require_once NOTIFIER_PATH . 'includes/classes/integrations/class-notifier-wsform.php';
429 Notifier_WSForm::init();
430 }
431 }
432
433 /**
434 * Is connection to WANotifier.com active?
435 */
436 public static function is_api_active () {
437 $activated = get_option(NOTIFIER_PREFIX . 'api_activated');
438 if('yes' == $activated) {
439 return true;
440 }
441 else{
442 return false;
443 }
444 }
445
446 /**
447 * Create New db table-- wanotifier_activity_log
448 */
449 public static function create_notifier_activity_log_table() {
450 global $wpdb;
451 $table_name = $wpdb->prefix . NOTIFIER_ACTIVITY_TABLE_NAME;
452
453 $charset_collate = $wpdb->get_charset_collate();
454
455 // Include IF NOT EXISTS clause in the CREATE TABLE query
456 $sql = "CREATE TABLE IF NOT EXISTS $table_name (
457 log_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
458 timestamp timestamp NOT NULL,
459 message text NOT NULL,
460 type varchar(16) NOT NULL,
461 PRIMARY KEY (log_id),
462 INDEX idx_timestamp (timestamp)
463 ) $charset_collate;";
464
465 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
466 dbDelta( $sql );
467
468 $notifier_plugin_data = get_option('notifier_meta', array());
469 $notifier_plugin_data['activity_log_table'] = 'yes';
470 update_option('notifier_meta', $notifier_plugin_data);
471 }
472
473 /**
474 * Delete old log from activity table according to interval
475 */
476 public function notifier_delete_old_activity_logs() {
477 global $wpdb;
478 $table_name = $wpdb->prefix . NOTIFIER_ACTIVITY_TABLE_NAME;
479 $retention_time = apply_filters( 'notifier_logs_retention_time', 7 );
480 $retention_time = intval($retention_time);
481 $wpdb->query( $wpdb->prepare( "DELETE FROM `$table_name` WHERE timestamp <= DATE_SUB(NOW(), INTERVAL %d DAY)", $retention_time ) );
482 }
483
484 /**
485 * Create New db table-- notifier_cart_abandonment
486 */
487 public static function create_cart_abandonment_table() {
488 if ( self::is_woo_handled_by_standalone_plugin() ) {
489 return;
490 }
491
492 $notifier_plugin_data = get_option('notifier_meta', array());
493 if ( ! isset( $notifier_plugin_data['cart_abandonment_table'] ) || $notifier_plugin_data['cart_abandonment_table'] !== 'yes' ) {
494 global $wpdb;
495 $table_name = $wpdb->prefix . NOTIFIER_CART_ABANDONMENT_TABLE;
496 $charset_collate = $wpdb->get_charset_collate();
497
498 // Updated CREATE TABLE query for notifier_cart_abandonment table
499 $sql = "CREATE TABLE IF NOT EXISTS $table_name (
500 session_id BIGINT(20) AUTO_INCREMENT PRIMARY KEY,
501 session_key VARCHAR(16) NULL,
502 phone_number VARCHAR(15) NULL,
503 cart_data LONGTEXT NULL,
504 cart_total DECIMAL(10,2) NULL,
505 coupon_data LONGTEXT NULL,
506 customer_data LONGTEXT NULL,
507 order_id BIGINT(11) DEFAULT 0,
508 triggered TINYINT(1) DEFAULT 0,
509 created_time DATETIME NULL,
510 updated_time DATETIME NULL,
511 KEY session_key (session_key) -- Index for session_key
512 ) $charset_collate;";
513
514 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
515 dbDelta( $sql );
516
517 $notifier_plugin_data['cart_abandonment_table'] = 'yes';
518 update_option('notifier_meta', $notifier_plugin_data);
519 }
520 }
521 }
522