Email Subscribers & Newsletters - Version 4.3.2

Version Description

Download this release

Release Info

Developer Icegram
Plugin Icon 128x128 Email Subscribers & Newsletters
Version 4.3.2
Comparing to
See all releases

Code changes from version 4.3.1 to 4.3.2

Files changed (49) hide show
  1. email-subscribers.php +3 -6
  2. lite/admin/class-email-subscribers-admin.php +24 -44
  3. lite/admin/css/email-subscribers-admin.css +47 -3
  4. lite/admin/js/email-subscribers-admin.js +4 -6
  5. lite/includes/class-email-subscribers-deactivator.php +8 -2
  6. lite/includes/class-email-subscribers.php +47 -35
  7. lite/includes/class-es-common.php +297 -203
  8. lite/includes/class-es-install.php +144 -49
  9. lite/includes/classes/class-es-actions.php +294 -0
  10. lite/includes/classes/class-es-admin-settings.php +794 -0
  11. lite/includes/classes/class-es-campaigns-table.php +432 -0
  12. lite/includes/classes/class-es-contacts-table.php +1110 -0
  13. lite/includes/classes/class-es-cron.php +438 -0
  14. lite/includes/classes/class-es-export-subscribers.php +334 -0
  15. lite/includes/classes/class-es-form-widget.php +80 -0
  16. lite/includes/classes/class-es-forms-table.php +834 -0
  17. lite/includes/classes/class-es-handle-post-notification.php +265 -0
  18. lite/includes/classes/class-es-handle-subscription.php +443 -0
  19. lite/includes/classes/class-es-handle-sync-wp-user.php +223 -0
  20. lite/includes/classes/class-es-import-subscribers.php +318 -0
  21. lite/includes/classes/class-es-info.php +55 -0
  22. lite/includes/classes/class-es-lists-table.php +640 -0
  23. lite/includes/classes/class-es-mailer.php +1146 -0
  24. lite/includes/classes/class-es-message.php +85 -0
  25. lite/includes/classes/class-es-newsletters.php +296 -0
  26. lite/includes/classes/class-es-old-widget.php +114 -0
  27. lite/includes/classes/class-es-post-notifications.php +393 -0
  28. lite/includes/classes/class-es-queue.php +737 -0
  29. lite/includes/classes/class-es-reports-data.php +72 -0
  30. lite/includes/classes/class-es-reports-table.php +518 -0
  31. lite/includes/classes/class-es-subscription-throttling.php +56 -0
  32. lite/includes/classes/class-es-templates-table.php +323 -0
  33. lite/includes/classes/class-es-tools.php +72 -0
  34. lite/includes/classes/class-es-tracking.php +39 -0
  35. lite/includes/classes/class-es-widget.php +87 -0
  36. lite/includes/db/class-es-db-actions.php +28 -0
  37. lite/includes/db/class-es-db-campaigns.php +0 -26
  38. lite/includes/db/class-es-db-contacts.php +51 -8
  39. lite/includes/db/class-es-db-lists-contacts.php +58 -1
  40. lite/includes/db/class-es-db-sending-queue.php +50 -15
  41. lite/includes/es-backward.php +5 -10
  42. lite/includes/es-core-functions.php +1 -0
  43. lite/includes/mailers/class-es-base-mailer.php +88 -1
  44. lite/includes/mailers/class-es-pepipost-mailer.php +65 -31
  45. lite/includes/mailers/class-es-phpmail-mailer.php +51 -0
  46. lite/includes/mailers/class-es-wpmail-mailer.php +45 -0
  47. lite/includes/upgrade/es-update-functions.php +19 -1
  48. lite/public/class-email-subscribers-public.php +6 -10
  49. readme.txt +11 -1
email-subscribers.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Email Subscribers & Newsletters
4
  * Plugin URI: https://www.icegram.com/
5
  * Description: Add subscription forms on website, send HTML newsletters & automatically notify subscribers about new blog posts once it is published.
6
- * Version: 4.3.1
7
  * Author: Icegram
8
  * Author URI: https://www.icegram.com/
9
  * Requires at least: 3.9
@@ -55,7 +55,7 @@ if ( ! function_exists( 'ig_es_show_upgrade_pro_notice' ) ) {
55
  $url = admin_url( "plugins.php?plugin_status=upgrade" );
56
  ?>
57
  <div class="notice notice-error">
58
- <p><?php echo sprintf( __( 'You are using older version of <strong>Email Subscribers Premium</strong> plugin. It won\'t work because it needs plugin to be updated. Please update %s plugin.', 'email-subscribers-premium' ),
59
  '<a href="' . $url . '" target="_blank">' . __( 'Email Subscribers Premium', 'email-subscribers' ) . '</a>' ); ?></p>
60
  </div>
61
  <?php
@@ -115,7 +115,7 @@ if ( $is_premium ) {
115
  /* ***************************** Initial Compatibility Work (End) ******************* */
116
 
117
  if ( ! defined( 'ES_PLUGIN_VERSION' ) ) {
118
- define( 'ES_PLUGIN_VERSION', '4.3.1' );
119
  }
120
 
121
  // Plugin Folder Path.
@@ -212,6 +212,3 @@ if ( ! function_exists( 'ES' ) ) {
212
  // Start ES
213
  ES()->run();
214
 
215
-
216
-
217
-
3
  * Plugin Name: Email Subscribers & Newsletters
4
  * Plugin URI: https://www.icegram.com/
5
  * Description: Add subscription forms on website, send HTML newsletters & automatically notify subscribers about new blog posts once it is published.
6
+ * Version: 4.3.2
7
  * Author: Icegram
8
  * Author URI: https://www.icegram.com/
9
  * Requires at least: 3.9
55
  $url = admin_url( "plugins.php?plugin_status=upgrade" );
56
  ?>
57
  <div class="notice notice-error">
58
+ <p><?php echo sprintf( __( 'You are using older version of <strong>Email Subscribers Premium</strong> plugin. It won\'t work because it needs plugin to be updated. Please update %s plugin.', 'email-subscribers' ),
59
  '<a href="' . $url . '" target="_blank">' . __( 'Email Subscribers Premium', 'email-subscribers' ) . '</a>' ); ?></p>
60
  </div>
61
  <?php
115
  /* ***************************** Initial Compatibility Work (End) ******************* */
116
 
117
  if ( ! defined( 'ES_PLUGIN_VERSION' ) ) {
118
+ define( 'ES_PLUGIN_VERSION', '4.3.2' );
119
  }
120
 
121
  // Plugin Folder Path.
212
  // Start ES
213
  ES()->run();
214
 
 
 
 
lite/admin/class-email-subscribers-admin.php CHANGED
@@ -320,75 +320,55 @@ class Email_Subscribers_Admin {
320
  $lists->render();
321
  }
322
 
 
 
 
 
323
  public function load_post_notifications() {
324
  $post_notifications = ES_Post_Notifications_Table::get_instance();
325
  $post_notifications->es_notifications_callback();
326
  }
327
 
 
 
 
 
 
328
  public function load_newsletters() {
329
  $newsletters = ES_Newsletters::get_instance();
330
  $newsletters->es_newsletters_settings_callback();
331
  }
332
 
 
 
 
 
 
333
  public function load_reports() {
334
  $reports = ES_Reports_Table::get_instance();
335
  $reports->es_reports_callback();
336
  }
337
 
 
 
 
 
 
338
  public function load_settings() {
339
  $settings = ES_Admin_Settings::get_instance();
340
  $settings->es_settings_callback();
341
  }
342
 
 
 
 
 
 
343
  public function load_preview() {
344
  $preview = ES_Templates_Table::get_instance();
345
  $preview->es_template_preview_callback();
346
  }
347
 
348
- public function do_send( $response, $data ) {
349
- global $phpmailer;
350
-
351
- if ( ! is_object( $phpmailer ) || ! is_a( $phpmailer, 'PHPMailer' ) ) {
352
- require_once ABSPATH . WPINC . '/class-phpmailer.php';
353
- $phpmailer = new PHPMailer( true );
354
- }
355
-
356
- $to_email = $data['to_email'];
357
- $subject = $data['subject'];
358
- $email_template = $data['email_template'];
359
- $headers = $data['headers'];
360
-
361
- $result = array( 'status' => 'SUCCESS' );
362
-
363
- // Get the Mailer Settings
364
- $ig_es_mailer_settings = get_option( 'ig_es_mailer_settings' );
365
-
366
- $mailer = $ig_es_mailer_settings['mailer'];
367
-
368
- $mailer_classname = 'ES_' . ucfirst( $mailer ) . '_Mailer';
369
- $is_mailer_file_exist = ( class_exists( $mailer_classname ) ) ? true : false;
370
-
371
- // If Specific Mailer Class Exists, send email through Mailer
372
- // Or send email through wp_mail();
373
- if ( $mailer != 'wpmail' && $is_mailer_file_exist ) {
374
- $mailer_instance = new $mailer_classname();
375
- $send_mail = $mailer_instance->send( $response, $data );
376
- } else {
377
- $send_mail = wp_mail( $to_email, $subject, $email_template, $headers );
378
- }
379
-
380
- if ( ! $send_mail || $send_mail['status'] === 'ERROR' ) {
381
-
382
- $result = array(
383
- 'status' => 'ERROR',
384
- 'message' => ! empty( $send_mail['message'] ) ? $send_mail['message'] : wp_strip_all_tags( $phpmailer->ErrorInfo )
385
- );
386
-
387
- }
388
-
389
- return $result;
390
- }
391
-
392
  function submenu_order( $menu_order ) {
393
  global $submenu;
394
 
320
  $lists->render();
321
  }
322
 
323
+ /**
324
+ * Render Post Notifications
325
+ * @since 4.2.1
326
+ */
327
  public function load_post_notifications() {
328
  $post_notifications = ES_Post_Notifications_Table::get_instance();
329
  $post_notifications->es_notifications_callback();
330
  }
331
 
332
+ /**
333
+ * Render Newsletters
334
+ *
335
+ * @since 4.2.1
336
+ */
337
  public function load_newsletters() {
338
  $newsletters = ES_Newsletters::get_instance();
339
  $newsletters->es_newsletters_settings_callback();
340
  }
341
 
342
+ /**
343
+ * Render Reports
344
+ *
345
+ * @since 4.2.1
346
+ */
347
  public function load_reports() {
348
  $reports = ES_Reports_Table::get_instance();
349
  $reports->es_reports_callback();
350
  }
351
 
352
+ /**
353
+ * Render Settings
354
+ *
355
+ * @since 4.2.1
356
+ */
357
  public function load_settings() {
358
  $settings = ES_Admin_Settings::get_instance();
359
  $settings->es_settings_callback();
360
  }
361
 
362
+ /**
363
+ * Render Preview
364
+ *
365
+ * @since 4.2.1
366
+ */
367
  public function load_preview() {
368
  $preview = ES_Templates_Table::get_instance();
369
  $preview->es_template_preview_callback();
370
  }
371
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  function submenu_order( $menu_order ) {
373
  global $submenu;
374
 
lite/admin/css/email-subscribers-admin.css CHANGED
@@ -593,7 +593,7 @@ p.search-box.box-ma10 {
593
  }
594
 
595
  #klawoo_response {
596
- background-color: yellow;
597
  }
598
 
599
  .es-about-line {
@@ -820,11 +820,11 @@ h5.es-badge {
820
  }
821
 
822
  .subscribed.es_list_contact_status:before {
823
- color: #0fc50f;
824
  }
825
 
826
  .unsubscribed.es_list_contact_status:before {
827
- color: #c5310f;
828
  }
829
 
830
  .unconfirmed.es_list_contact_status:before {
@@ -1275,6 +1275,7 @@ div.es .last {
1275
  padding: 10px;
1276
  font-size: 16px;
1277
  height: auto;
 
1278
  }
1279
  .es_settings_field label{
1280
  font-size: 0.9em;
@@ -1299,6 +1300,7 @@ div.es .last {
1299
  padding-right: 20px;
1300
  background-color: #FFF !important;
1301
  width: 100%;
 
1302
  }
1303
  .es_campaign_name_wrapper{
1304
  margin-bottom: 1em;
@@ -1317,6 +1319,7 @@ div.es .last {
1317
  padding: 10px;
1318
  font-size: 16px;
1319
  height: auto;
 
1320
  }
1321
  .es_primary_btn{
1322
  font-size: 1.2em;
@@ -1352,4 +1355,45 @@ div.es .last {
1352
  color: #000;
1353
  background: #FFF;
1354
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1355
  /* Email Subscribers new css : End*/
593
  }
594
 
595
  #klawoo_response {
596
+ /*background-color: yellow;*/
597
  }
598
 
599
  .es-about-line {
820
  }
821
 
822
  .subscribed.es_list_contact_status:before {
823
+ color: #009e00;
824
  }
825
 
826
  .unsubscribed.es_list_contact_status:before {
827
+ color: #d40303;
828
  }
829
 
830
  .unconfirmed.es_list_contact_status:before {
1275
  padding: 10px;
1276
  font-size: 16px;
1277
  height: auto;
1278
+ line-height: 1;
1279
  }
1280
  .es_settings_field label{
1281
  font-size: 0.9em;
1300
  padding-right: 20px;
1301
  background-color: #FFF !important;
1302
  width: 100%;
1303
+ max-width: 100%;
1304
  }
1305
  .es_campaign_name_wrapper{
1306
  margin-bottom: 1em;
1319
  padding: 10px;
1320
  font-size: 16px;
1321
  height: auto;
1322
+ line-height: 1;
1323
  }
1324
  .es_primary_btn{
1325
  font-size: 1.2em;
1355
  color: #000;
1356
  background: #FFF;
1357
  }
1358
+
1359
+ /* Contact reports */
1360
+ .es-contact-reports{
1361
+ border-top: 2px solid #ccc;
1362
+ margin-top: 1em;
1363
+ padding-bottom: 1.2em;
1364
+ /*border-bottom: 1px solid #ccc;*/
1365
+ }
1366
+ .es-contact-reports h2{
1367
+ margin:0.6em 0;
1368
+ }
1369
+ .es-contact-reports .es_total_contact{
1370
+ width: 8em;
1371
+ float: left;
1372
+ border-right: 1px dashed #CCC;
1373
+ height: 7em;
1374
+ margin-left: 1em;
1375
+ }
1376
+ .es-contact-reports .es_total_contact .es_contact_kpi_no{
1377
+ font-size: 3em;
1378
+ line-height: 1em;
1379
+ }
1380
+ .es-contact-reports .es_last_60_days{
1381
+ width: 70%;
1382
+ margin-left: 2em;
1383
+ display: inline-block;
1384
+ }
1385
+ .es_contact_kpi{
1386
+ width: auto;
1387
+ display: inline-block;
1388
+ margin-right: 1em;
1389
+ min-width: 4em;
1390
+ }
1391
+ .es_contact_kpi .es_contact_kpi_no{
1392
+ font-size: 1.5em;
1393
+ line-height: 1.8em;
1394
+ font-weight:500;
1395
+ }
1396
+ .es_contact_kpi .es_contact_kpi_text{
1397
+ color: #636363;
1398
+ }
1399
  /* Email Subscribers new css : End*/
lite/admin/js/email-subscribers-admin.js CHANGED
@@ -115,14 +115,12 @@
115
  data: params,
116
  success: function(response) {
117
  if (response != '') {
118
- var parser = new DOMParser()
119
- var el = parser.parseFromString(response, "text/xml");
120
- var msg = el.childNodes[0].firstChild.nextElementSibling.innerHTML;
121
  if (jQuery(form).hasClass('es-onboarding')) {
122
- location.reload();
 
 
123
  } else {
124
- jQuery(form).find('#klawoo_response').html();
125
-
126
  jQuery('.es-emm-optin #name').val('');
127
  jQuery('.es-emm-optin #email').val('');
128
  jQuery('.es-emm-optin #es-gdpr-agree').attr('checked', false);
115
  data: params,
116
  success: function(response) {
117
  if (response != '') {
118
+ jQuery('#klawoo_response').html(response);
 
 
119
  if (jQuery(form).hasClass('es-onboarding')) {
120
+ setTimeout(function() {
121
+ location.reload();
122
+ }, 2000);
123
  } else {
 
 
124
  jQuery('.es-emm-optin #name').val('');
125
  jQuery('.es-emm-optin #email').val('');
126
  jQuery('.es-emm-optin #es-gdpr-agree').attr('checked', false);
lite/includes/class-email-subscribers-deactivator.php CHANGED
@@ -32,10 +32,16 @@ class Email_Subscribers_Deactivator {
32
  *
33
  * Long Description.
34
  *
35
- * @since 4.0
 
36
  */
37
  public static function deactivate() {
38
-
 
 
 
 
 
39
  }
40
 
41
  }
32
  *
33
  * Long Description.
34
  *
35
+ * @since 4.0
36
+ * @since 4.3.2 Clear all schedule crons
37
  */
38
  public static function deactivate() {
39
+ /**
40
+ * Cleanup all plugin related stuff in plugin deactivation
41
+ *
42
+ * @since 4.3.2
43
+ */
44
+ do_action('ig_es_plugin_deactivate');
45
  }
46
 
47
  }
lite/includes/class-email-subscribers.php CHANGED
@@ -140,7 +140,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
140
  */
141
  public $lists_db;
142
 
143
-
144
  /**
145
  * @since 4.2.1
146
  * @var object|ES_Forms_Table
@@ -200,6 +199,13 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
200
  */
201
  public $logger;
202
 
 
 
 
 
 
 
 
203
  /**
204
  * The loader that's responsible for maintaining and registering all hooks that power
205
  * the plugin.
@@ -489,6 +495,9 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
489
  if ( ! defined( 'IG_MESSAGE_ERROR' ) ) {
490
  define( 'IG_MESSAGE_ERROR', 8 );
491
  }
 
 
 
492
  }
493
 
494
  /**
@@ -554,38 +563,42 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
554
  'lite/includes/db/class-es-db-actions.php',
555
 
556
  // Mailers
557
- 'lite/includes/class-es-mailer.php',
558
  'lite/includes/mailers/class-es-base-mailer.php',
559
  'lite/includes/mailers/class-es-pepipost-mailer.php',
 
 
560
 
561
  // Common Class
562
  'lite/includes/class-es-common.php',
563
 
564
- // Admin Classes
565
- 'lite/includes/admin/class-es-lists-table.php',
566
- 'lite/includes/admin/class-es-contacts-table.php',
567
- 'lite/includes/admin/class-es-post-notifications.php',
568
- 'lite/includes/admin/class-es-templates-table.php',
569
- 'lite/includes/admin/class-es-campaigns-table.php',
570
- 'lite/includes/admin/class-es-reports-table.php',
571
- 'lite/includes/admin/class-es-forms-table.php',
572
- 'lite/includes/admin/class-es-queue.php',
573
- 'lite/includes/admin/class-es-cron.php',
574
- 'lite/includes/admin/class-es-newsletters.php',
575
- 'lite/includes/admin/class-es-tools.php',
576
- 'lite/includes/admin/class-es-admin-settings.php',
577
- 'lite/includes/admin/class-es-widget.php',
578
- 'lite/includes/admin/class-es-old-widget.php',
579
- 'lite/includes/admin/class-es-form-widget.php',
580
- 'lite/includes/admin/class-es-export-subscribers.php',
581
- 'lite/includes/admin/class-es-import-subscribers.php',
582
- 'lite/includes/admin/class-es-info.php',
583
- 'lite/includes/admin/class-es-handle-post-notification.php',
584
- 'lite/includes/admin/class-es-handle-subscription.php',
585
- 'lite/includes/admin/class-es-handle-sync-wp-user.php',
586
- 'lite/includes/admin/class-es-subscription-throttaling.php',
587
- 'lite/includes/admin/class-es-actions.php',
588
- 'lite/includes/admin/class-es-tracking.php',
 
 
 
589
 
590
  // Core Functions
591
  'lite/includes/es-core-functions.php',
@@ -660,16 +673,11 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
660
  $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
661
  $this->loader->add_action( 'plugins_loaded', $plugin_admin, 'plugins_loaded' );
662
 
663
- $this->loader->add_filter( 'ig_es_lite_do_send', $plugin_admin, 'do_send', 10, 2 );
664
  $this->loader->add_filter( 'set-screen-option', $plugin_admin, 'save_screen_options', 20, 3 );
665
 
666
  $this->loader->add_action( 'wp_ajax_count_contacts_by_list', $plugin_admin, 'count_contacts_by_list' );
667
  $this->loader->add_action( 'wp_ajax_get_template_content', $plugin_admin, 'get_template_content' );
668
 
669
- //$this->loader->add_filter( 'ig_es_blocked_domains', $plugin_admin, 'blocked_domains', 10, 1 );
670
- //$this->loader->add_filter( 'ig_es_whitelist_ips', $plugin_admin, 'whitelist_ips', 10, 1 );
671
- //$this->loader->add_filter( 'ig_es_blacklist_ips', $plugin_admin, 'blacklist_ips', 10, 1 );
672
-
673
  }
674
 
675
  /**
@@ -769,8 +777,9 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
769
  public function log_errors() {
770
  $error = error_get_last();
771
  if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ), true ) ) {
 
772
 
773
- ES()->logger->critical(
774
  sprintf( __( '%1$s in %2$s on line %3$s', 'email-subscribers' ), $error['message'], $error['file'], $error['line'] ) . PHP_EOL,
775
  array(
776
  'source' => 'fatal-errors',
@@ -794,8 +803,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
794
 
795
  self::$instance = new Email_Subscribers();
796
 
797
- register_shutdown_function( array( self::$instance, 'log_errors' ) );
798
-
799
  require_once plugin_dir_path( __FILE__ ) . 'class-email-subscribers-activator.php';
800
  require_once plugin_dir_path( __FILE__ ) . 'class-email-subscribers-deactivator.php';
801
 
@@ -807,8 +814,13 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
807
  self::$instance->define_admin_hooks();
808
  self::$instance->define_public_hooks();
809
 
 
 
810
  self::$instance->logger = get_ig_logger();
811
 
 
 
 
812
  add_action( 'widgets_init', array( self::$instance, 'register_es_widget' ) );
813
 
814
  self::$instance->queue_db = new ES_DB_Queue();
140
  */
141
  public $lists_db;
142
 
 
143
  /**
144
  * @since 4.2.1
145
  * @var object|ES_Forms_Table
199
  */
200
  public $logger;
201
 
202
+ /**
203
+ * @since 4.3.1
204
+ *
205
+ * @var object|ES_Mailer
206
+ */
207
+ public $mailer;
208
+
209
  /**
210
  * The loader that's responsible for maintaining and registering all hooks that power
211
  * the plugin.
495
  if ( ! defined( 'IG_MESSAGE_ERROR' ) ) {
496
  define( 'IG_MESSAGE_ERROR', 8 );
497
  }
498
+ if ( ! defined( 'IG_ES_CRON_INTERVAL' ) ) {
499
+ define( 'IG_ES_CRON_INTERVAL', 15 * MINUTE_IN_SECONDS );
500
+ }
501
  }
502
 
503
  /**
563
  'lite/includes/db/class-es-db-actions.php',
564
 
565
  // Mailers
 
566
  'lite/includes/mailers/class-es-base-mailer.php',
567
  'lite/includes/mailers/class-es-pepipost-mailer.php',
568
+ 'lite/includes/mailers/class-es-phpmail-mailer.php',
569
+ 'lite/includes/mailers/class-es-wpmail-mailer.php',
570
 
571
  // Common Class
572
  'lite/includes/class-es-common.php',
573
 
574
+ // Classes
575
+ 'lite/includes/classes/class-es-mailer.php',
576
+ 'lite/includes/classes/class-es-message.php',
577
+ 'lite/includes/classes/class-es-lists-table.php',
578
+ 'lite/includes/classes/class-es-contacts-table.php',
579
+ 'lite/includes/classes/class-es-post-notifications.php',
580
+ 'lite/includes/classes/class-es-templates-table.php',
581
+ 'lite/includes/classes/class-es-campaigns-table.php',
582
+ 'lite/includes/classes/class-es-reports-table.php',
583
+ 'lite/includes/classes/class-es-reports-data.php',
584
+ 'lite/includes/classes/class-es-forms-table.php',
585
+ 'lite/includes/classes/class-es-queue.php',
586
+ 'lite/includes/classes/class-es-cron.php',
587
+ 'lite/includes/classes/class-es-newsletters.php',
588
+ 'lite/includes/classes/class-es-tools.php',
589
+ 'lite/includes/classes/class-es-admin-settings.php',
590
+ 'lite/includes/classes/class-es-widget.php',
591
+ 'lite/includes/classes/class-es-old-widget.php',
592
+ 'lite/includes/classes/class-es-form-widget.php',
593
+ 'lite/includes/classes/class-es-export-subscribers.php',
594
+ 'lite/includes/classes/class-es-import-subscribers.php',
595
+ 'lite/includes/classes/class-es-info.php',
596
+ 'lite/includes/classes/class-es-handle-post-notification.php',
597
+ 'lite/includes/classes/class-es-handle-subscription.php',
598
+ 'lite/includes/classes/class-es-handle-sync-wp-user.php',
599
+ 'lite/includes/classes/class-es-subscription-throttling.php',
600
+ 'lite/includes/classes/class-es-actions.php',
601
+ 'lite/includes/classes/class-es-tracking.php',
602
 
603
  // Core Functions
604
  'lite/includes/es-core-functions.php',
673
  $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
674
  $this->loader->add_action( 'plugins_loaded', $plugin_admin, 'plugins_loaded' );
675
 
 
676
  $this->loader->add_filter( 'set-screen-option', $plugin_admin, 'save_screen_options', 20, 3 );
677
 
678
  $this->loader->add_action( 'wp_ajax_count_contacts_by_list', $plugin_admin, 'count_contacts_by_list' );
679
  $this->loader->add_action( 'wp_ajax_get_template_content', $plugin_admin, 'get_template_content' );
680
 
 
 
 
 
681
  }
682
 
683
  /**
777
  public function log_errors() {
778
  $error = error_get_last();
779
  if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ), true ) ) {
780
+ $logger = get_ig_logger();
781
 
782
+ $logger->critical(
783
  sprintf( __( '%1$s in %2$s on line %3$s', 'email-subscribers' ), $error['message'], $error['file'], $error['line'] ) . PHP_EOL,
784
  array(
785
  'source' => 'fatal-errors',
803
 
804
  self::$instance = new Email_Subscribers();
805
 
 
 
806
  require_once plugin_dir_path( __FILE__ ) . 'class-email-subscribers-activator.php';
807
  require_once plugin_dir_path( __FILE__ ) . 'class-email-subscribers-deactivator.php';
808
 
814
  self::$instance->define_admin_hooks();
815
  self::$instance->define_public_hooks();
816
 
817
+ //register_shutdown_function( array( self::$instance, 'log_errors' ) );
818
+
819
  self::$instance->logger = get_ig_logger();
820
 
821
+
822
+ self::$instance->mailer = new ES_Mailer();
823
+
824
  add_action( 'widgets_init', array( self::$instance, 'register_es_widget' ) );
825
 
826
  self::$instance->queue_db = new ES_DB_Queue();
lite/includes/class-es-common.php CHANGED
@@ -5,18 +5,12 @@ if ( ! defined( 'ABSPATH' ) ) {
5
  exit;
6
  }
7
 
8
-
9
  /**
10
  * Class Email_General.
11
  *
12
  * @since 4.0
13
  */
14
  Class ES_Common {
15
-
16
- public function __construct() {
17
-
18
- }
19
-
20
  /**
21
  * Convert email subscribe templates.
22
  *
@@ -25,8 +19,8 @@ Class ES_Common {
25
  * @param string $email Get subscriber email.
26
  *
27
  * @return string $convert_template
28
- * @since 4.0
29
  *
 
30
  */
31
  public static function convert_es_templates( $template, $name, $email, $es_templ_id = 0 ) {
32
  $convert_template = str_replace( "{{NAME}}", $name, $template );
@@ -35,19 +29,30 @@ Class ES_Common {
35
  return $convert_template;
36
  }
37
 
 
 
 
 
 
 
 
 
 
 
 
38
  public static function es_process_template_body( $content, $tmpl_id = 0, $campaign_id = 0 ) {
39
  $content = convert_chars( convert_smilies( wptexturize( $content ) ) );
40
  if ( isset( $GLOBALS['wp_embed'] ) ) {
41
  $content = $GLOBALS['wp_embed']->autoembed( $content );
42
  }
43
 
44
- $content = wpautop( $content );
45
- $content = do_shortcode( shortcode_unautop( $content ) );
46
- $data['content'] = $content;
47
- $data['tmpl_id'] = $tmpl_id;
48
  $data['campaign_id'] = $campaign_id;
49
- $data = apply_filters( 'es_after_process_template_body', $data );
50
- $content = $data['content'];
51
  //total contacts
52
  $total_contacts = ES()->contacts_db->count_active_contacts_by_list_id();
53
  $content = str_replace( "{{TOTAL-CONTACTS}}", $total_contacts, $content );
@@ -57,30 +62,32 @@ Class ES_Common {
57
  // site url
58
  $site_url = home_url( '/' );
59
  $content = str_replace( "{{SITEURL}}", $site_url, $content );
 
 
 
 
 
 
 
60
 
61
  return $content;
62
  }
63
 
64
  /**
65
- * Get html content type.
66
  *
67
- * @return string
68
- * @since 4.0
 
69
  *
 
70
  */
71
- public static function es_set_html_content_type() {
72
- return 'text/html';
73
- }
74
-
75
  public static function get_statuses_key_name_map( $reverse = false ) {
76
 
77
  $statuses = array(
78
- // 'confirmed' => __( 'Confirmed', 'email-subscribers' ),
79
  'subscribed' => __( 'Subscribed', 'email-subscribers' ),
80
  'unconfirmed' => __( 'Unconfirmed', 'email-subscribers' ),
81
- 'unsubscribed' => __( 'Unsubscribed', 'email-subscribers' ),
82
- // 'single_opt_in' => __( 'Single Opt In', 'email-subscribers' ),
83
- // 'double_opt_in' => __( 'Double Opt In', 'email-subscribers' )
84
  );
85
 
86
  if ( $reverse ) {
@@ -90,23 +97,18 @@ Class ES_Common {
90
  return $statuses;
91
  }
92
 
93
-
94
- public static function get_email_sent_type_key_name_map() {
95
- $options = array(
96
- '0' => __( 'Disable email notification', 'email-subscribers' ),
97
- '1' => __( 'Send email immediately', 'email-subscribers' ),
98
- '2' => __( 'Send email via cron job', 'email-subscribers' )
99
- );
100
-
101
- return $options;
102
- }
103
-
104
  public static function prepare_statuses_dropdown_options( $selected = '', $default_label = 'Select Status' ) {
105
 
106
- // $default_status = array(
107
- // '' => __( 'Select Status', 'email-subscribers' ),
108
-
109
- // );
110
  $default_status[0] = __( $default_label, 'email-subscribers' );
111
 
112
  $statuses = self::get_statuses_key_name_map();
@@ -126,6 +128,16 @@ Class ES_Common {
126
  return $dropdown;
127
  }
128
 
 
 
 
 
 
 
 
 
 
 
129
  public static function prepare_list_dropdown_options( $selected = '', $default_label = 'Select List' ) {
130
 
131
  $default_option[0] = __( $default_label, 'email-subscribers' );
@@ -147,48 +159,47 @@ Class ES_Common {
147
  return $dropdown;
148
  }
149
 
 
 
 
 
 
 
 
 
 
150
  public static function prepare_form_dropdown_options( $selected = '', $default_label = 'Select Form' ) {
151
 
152
- $where = "(deleted_at IS NULL OR deleted_at = '0000-00-00 00:00:00')";
153
-
154
- $lists = ES()->forms_db->get_id_name_map( $where );
155
 
156
  if ( ! is_null( $default_label ) ) {
157
  $default_option[0] = __( $default_label, 'email-subscribers' );
158
- $lists = $default_option + $lists;
159
  }
160
 
161
  $dropdown = '';
162
- foreach ( $lists as $key => $list ) {
163
  $dropdown .= "<option value='{$key}'";
164
 
165
  if ( $selected == $key ) {
166
  $dropdown .= "selected = selected";
167
  }
168
 
169
- $dropdown .= ">{$list}</option>";
170
  }
171
 
172
  return $dropdown;
173
  }
174
 
175
-
176
- public static function prepare_list_checkbox( $selected = array() ) {
177
- $lists = ES()->lists_db->get_list_id_name_map();
178
-
179
- $html = '';
180
- foreach ( $lists as $key => $list ) {
181
- if ( in_array( $key, $selected ) ) {
182
- $checked = "checked='checked'";
183
- } else {
184
- $checked = "";
185
- }
186
- $html .= '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><input type="checkbox" ' . $checked . ' value="' . $key . '" id="list_ids[]" name="list_ids[]">' . $list . '</td></tr>';
187
- }
188
-
189
- return $html;
190
- }
191
-
192
  public static function generate_guid( $length = 6 ) {
193
 
194
  $str = 'abcdefghijklmnopqrstuvwxyz';
@@ -202,80 +213,14 @@ Class ES_Common {
202
  return $guid;
203
  }
204
 
205
- public static function es_handle_error( $errno, $errstr, $errfile, $errline ) {
206
-
207
- if ( $errno === E_USER_NOTICE ) {
208
-
209
- $message = 'You have an error notice: "%s" in file "%s" at line: "%s".';
210
- $message = sprintf( $message, $errstr, $errfile, $errline );
211
- }
212
- }
213
-
214
- public static function es_generate_stack_trace() {
215
-
216
- $e = new \Exception();
217
-
218
- $trace = explode( "\n", $e->getTraceAsString() );
219
-
220
- // reverse array to make steps line up chronologically
221
-
222
- $trace = array_reverse( $trace );
223
-
224
- array_shift( $trace ); // remove {main}
225
- array_pop( $trace ); // remove call to this method
226
-
227
- $length = count( $trace );
228
- $result = array();
229
-
230
- for ( $i = 0; $i < $length; $i ++ ) {
231
- $result[] = ( $i + 1 ) . ')' . substr( $trace[ $i ], strpos( $trace[ $i ], ' ' ) ); // replace '#someNum' with '$i)', set the right ordering
232
- }
233
-
234
- $result = implode( "\n", $result );
235
- $result = "\n" . $result . "\n";
236
-
237
- return $result;
238
- }
239
-
240
- public static function prepare_list_statuses_dropdown_options( $selected = '' ) {
241
-
242
- $statuses = array(
243
- '' => __( 'Select Status', 'email-subscribers' ),
244
- 'enable' => __( 'Enable', 'email-subscribers' ),
245
- 'disable' => __( 'Disable', 'email-subscribers' )
246
- );
247
-
248
- $dropdown = '';
249
- foreach ( $statuses as $key => $status ) {
250
- $dropdown .= "<option value='{$key}'";
251
-
252
- if ( strtolower( $selected ) === strtolower( $key ) ) {
253
- $dropdown .= "selected = selected";
254
- }
255
-
256
- $dropdown .= ">{$status}</option>";
257
- }
258
-
259
- return $dropdown;
260
- }
261
-
262
- public static function prepare_notification_send_type_dropdown_options( $selected = '' ) {
263
- $options = ES_Common::get_email_sent_type_key_name_map();
264
- $dropdown = '';
265
- foreach ( $options as $key => $option ) {
266
- $dropdown .= "<option value='{$key}'";
267
-
268
- if ( strtolower( $selected ) === strtolower( $key ) ) {
269
- $dropdown .= "selected = selected";
270
- }
271
-
272
- $dropdown .= ">{$option}</option>";
273
- }
274
-
275
- return $dropdown;
276
- }
277
-
278
-
279
  public static function prepare_templates_dropdown_options( $type = 'newsletter', $selected = '' ) {
280
 
281
  $default_template_option = new stdClass();
@@ -308,6 +253,15 @@ Class ES_Common {
308
 
309
  }
310
 
 
 
 
 
 
 
 
 
 
311
  public static function prepare_status_dropdown_options( $selected ) {
312
  $statuses = array(
313
  '1' => __( 'Active', 'email-subscribers' ),
@@ -328,6 +282,15 @@ Class ES_Common {
328
  return $dropdown;
329
  }
330
 
 
 
 
 
 
 
 
 
 
331
  public static function get_templates( $type = 'newsletter' ) {
332
 
333
  $es_args = array(
@@ -352,6 +315,15 @@ Class ES_Common {
352
 
353
  }
354
 
 
 
 
 
 
 
 
 
 
355
  public static function prepare_categories_html( $category_names = array() ) {
356
  $categories = get_terms( array(
357
  'taxonomy' => 'category',
@@ -364,8 +336,6 @@ Class ES_Common {
364
  $category_html = '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><input class="es-note-category-parent" type="radio" ' . $checked_selected . ' value="selected_cat" name="es_note_cat_parent">' . __( 'Select Categories', 'email-subscribers' ) . '</td></tr>';
365
  foreach ( $categories as $category ) {
366
 
367
- // $category_str = wp_specialchars_decode( $category->name, ENT_QUOTES );
368
-
369
  if ( in_array( $category->term_id, $category_names ) ) {
370
  $checked = "checked='checked'";
371
  } else {
@@ -380,6 +350,15 @@ Class ES_Common {
380
  return $all_html . $category_html;
381
  }
382
 
 
 
 
 
 
 
 
 
 
383
  public static function prepare_custom_post_type_checkbox( $custom_post_types ) {
384
  $args = array( 'public' => true, 'exclude_from_search' => false, '_builtin' => false );
385
  $output = 'names';
@@ -404,18 +383,13 @@ Class ES_Common {
404
  return $custom_post_type_html;
405
  }
406
 
407
- public static function get_email_sending_type() {
408
-
409
- $types = array(
410
- 'wp_html_mail' => __( 'HTML Email Using WordPress', 'email-subsribers' ),
411
- 'wp_plaintext_mail' => __( 'Plain Text Email Using WordPress', 'email-subsribers' ),
412
- 'php_html_mail' => __( 'HTML Email Using PHP mail()', 'email-subsribers' ),
413
- 'php_plaintext_mail' => __( 'Plain Text Email Ising PHP mail()', 'email-subsribers' )
414
- );
415
-
416
- return $types;
417
- }
418
-
419
  public static function get_optin_types() {
420
 
421
  $types = array(
@@ -426,6 +400,13 @@ Class ES_Common {
426
  return $types;
427
  }
428
 
 
 
 
 
 
 
 
429
  public static function get_image_sizes() {
430
  $sizes = array(
431
  'full' => __( 'Full Size', 'email-subscribers' ),
@@ -436,6 +417,16 @@ Class ES_Common {
436
  return $sizes;
437
  }
438
 
 
 
 
 
 
 
 
 
 
 
439
  public static function get_ig_option( $option, $default = null ) {
440
 
441
  if ( empty( $option ) ) {
@@ -448,6 +439,16 @@ Class ES_Common {
448
 
449
  }
450
 
 
 
 
 
 
 
 
 
 
 
451
  public static function set_ig_option( $option, $value ) {
452
 
453
  if ( empty( $option ) ) {
@@ -479,7 +480,15 @@ Class ES_Common {
479
  return delete_option( $option_prefix . $option );
480
  }
481
 
482
-
 
 
 
 
 
 
 
 
483
  public static function convert_categories_array_to_string( $categories = array() ) {
484
 
485
  $categories_str = '';
@@ -492,6 +501,16 @@ Class ES_Common {
492
  return $categories_str;
493
  }
494
 
 
 
 
 
 
 
 
 
 
 
495
  public static function convert_categories_string_to_array( $categories_str = '', $keep_ids = true ) {
496
  $categories = array();
497
  if ( strlen( $categories_str ) > 0 ) {
@@ -507,6 +526,15 @@ Class ES_Common {
507
  return $categories;
508
  }
509
 
 
 
 
 
 
 
 
 
 
510
  public static function convert_id_to_name( $category ) {
511
  if ( $category != 'All' ) {
512
  return get_cat_name( $category );
@@ -515,7 +543,15 @@ Class ES_Common {
515
  }
516
  }
517
 
518
-
 
 
 
 
 
 
 
 
519
  public static function convert_name_to_id( $category ) {
520
  if ( strpos( $category, '{T}' ) === false ) {
521
  $category = wp_specialchars_decode( addslashes( $category ) );
@@ -526,16 +562,33 @@ Class ES_Common {
526
  }
527
  }
528
 
 
 
 
 
 
 
 
 
 
529
  public static function prepare_category_string( $category = '' ) {
530
  $category_str = '';
531
  if ( ! empty( $category ) ) {
532
- $category = wp_specialchars_decode( $category, ENT_QUOTES );
533
  $category_str = "##" . $category . "##";
534
  }
535
 
536
  return $category_str;
537
  }
538
 
 
 
 
 
 
 
 
 
 
539
  public static function prepare_custom_post_type_string( $post_type = '' ) {
540
  $post_type_str = '';
541
  if ( ! empty( $post_type ) ) {
@@ -545,6 +598,15 @@ Class ES_Common {
545
  return $post_type_str;
546
  }
547
 
 
 
 
 
 
 
 
 
 
548
  public static function prepare_categories_migration_string( $categories_str ) {
549
  $categories = self::convert_categories_string_to_array( $categories_str, true );
550
  $categories = array_map( array( 'ES_Common', 'convert_name_to_id' ), $categories );
@@ -554,6 +616,15 @@ Class ES_Common {
554
 
555
  }
556
 
 
 
 
 
 
 
 
 
 
557
  public static function prepare_first_name_last_name( $name = '' ) {
558
  $result = array(
559
  'first_name' => '',
@@ -579,34 +650,16 @@ Class ES_Common {
579
  return $result;
580
  }
581
 
582
- public static function send_signup_notification_to_admins( $data ) {
583
-
584
- $ig_es_notifyadmin = get_option( 'ig_es_notify_admin', 'no' );
585
-
586
- if ( 'yes' === $ig_es_notifyadmin ) {
587
-
588
- $admin_email_addresses = get_option( 'ig_es_admin_emails', '' );
589
-
590
- if ( ! empty( $admin_email_addresses ) ) {
591
-
592
- $admin_emails = explode( ',', $admin_email_addresses );
593
-
594
- if ( count( $admin_emails ) > 0 ) {
595
- $subject = ES_Mailer::prepare_admin_signup_subject( $data );
596
- $content = ES_Mailer::prepare_admin_signup_email( $data );
597
- foreach ( $admin_emails as $admin_email ) {
598
- $email = trim( $admin_email );
599
- ES_Mailer::send( $email, $subject, $content );
600
- }
601
-
602
- return true;
603
- }
604
- }
605
- }
606
-
607
- return false;
608
- }
609
-
610
  public static function prepare_name_from_first_name_last_name( $first_name = '', $last_name = '' ) {
611
  $first_name = trim( $first_name );
612
  $last_name = trim( $last_name );
@@ -614,33 +667,27 @@ Class ES_Common {
614
  return trim( $first_name . ' ' . $last_name );
615
  }
616
 
 
 
 
 
 
 
 
 
 
617
  public static function get_name_from_email( $email ) {
618
  $name = strstr( $email, '@', true );
619
 
620
  return trim( $name );
621
  }
622
 
623
-
624
  /**
625
- * Check if Classic Editor plugin is active.
626
  *
627
- * @return bool
628
  */
629
- public static function is_classic_editor_plugin_active() {
630
-
631
- if ( ! function_exists( 'is_plugin_active' ) ) {
632
- include_once ABSPATH . 'wp-admin/includes/plugin.php';
633
- }
634
-
635
- if ( is_plugin_active( 'classic-editor/classic-editor.php' ) ) {
636
- return true;
637
- }
638
-
639
- return false;
640
- }
641
-
642
  public static function migrate_widgets() {
643
- global $wpdb;
644
  /**
645
  * Option - 1 -> ES < 3.x email-subscribers
646
  * Option - 2 -> ES < 4.0.4 email_subscriber_widget
@@ -659,7 +706,6 @@ Class ES_Common {
659
  * - Change Option 1 with Option 3
660
  * - Change Option 2 with Option 3
661
  */
662
-
663
  $es_3_widget_option = 'widget_email-subscribers';
664
  $es_4_widget_option = 'widget_email_subscriber_widget';
665
  $latest_widget_option = 'widget_email-subscribers-form';
@@ -787,10 +833,28 @@ Class ES_Common {
787
 
788
  }
789
 
 
 
 
 
 
 
 
 
 
790
  public static function temp_filter_category( $category ) {
791
  return trim( trim( $category ), '#' );
792
  }
793
 
 
 
 
 
 
 
 
 
 
794
  public static function show_message( $message = '', $status = 'success', $is_dismissible = true ) {
795
 
796
  $class = 'notice notice-success';
@@ -805,6 +869,13 @@ Class ES_Common {
805
  echo "<div class='{$class}'><p>{$message}</p></div>";
806
  }
807
 
 
 
 
 
 
 
 
808
  public static function prepare_main_header_navigation( $navigation_tabs ) {
809
 
810
  foreach ( $navigation_tabs as $key => $navigation ) {
@@ -822,14 +893,23 @@ Class ES_Common {
822
  } ?>"><?php echo $action_label; ?>
823
  <?php if ( $show_indicator ) { ?>
824
  <span class="ig-es-indicator <?php echo $indicator_class; ?>">
825
- <?php echo $indicator_label ?>
826
- </span>
827
 
828
  <?php } ?>
829
  </a>
830
  <?php }
831
  }
832
 
 
 
 
 
 
 
 
 
 
833
  public static function prepare_information_box( $info, $content_html ) {
834
 
835
  $default_args = array(
@@ -882,6 +962,7 @@ Class ES_Common {
882
  *
883
  * @param $params
884
  *
 
885
  */
886
  public static function render_feedback_widget( $params ) {
887
  global $ig_es_feedback;
@@ -949,6 +1030,13 @@ Class ES_Common {
949
 
950
  }
951
 
 
 
 
 
 
 
 
952
  public static function get_all_settings() {
953
 
954
  global $wpdb;
@@ -967,12 +1055,19 @@ Class ES_Common {
967
  return $options_name_value_map;
968
  }
969
 
 
 
 
 
 
 
 
970
  public static function get_ig_es_meta_info() {
971
 
972
  $total_contacts = ES()->contacts_db->count();
973
  $total_lists = ES()->lists_db->count_lists();
974
  $total_newsletters = ES()->campaigns_db->get_total_newsletters();
975
- $total_post_notifications = ES()->campaigns_db->get_total_post_notifications;
976
 
977
  $meta_info = array(
978
  'total_contacts' => $total_contacts,
@@ -1200,5 +1295,4 @@ Class ES_Common {
1200
 
1201
  return substr( md5( $auth_key . wp_rand( $length, 64 ) ), 0, $length );
1202
  }
1203
-
1204
  }
5
  exit;
6
  }
7
 
 
8
  /**
9
  * Class Email_General.
10
  *
11
  * @since 4.0
12
  */
13
  Class ES_Common {
 
 
 
 
 
14
  /**
15
  * Convert email subscribe templates.
16
  *
19
  * @param string $email Get subscriber email.
20
  *
21
  * @return string $convert_template
 
22
  *
23
+ * @since 4.0
24
  */
25
  public static function convert_es_templates( $template, $name, $email, $es_templ_id = 0 ) {
26
  $convert_template = str_replace( "{{NAME}}", $name, $template );
29
  return $convert_template;
30
  }
31
 
32
+ /**
33
+ * Process template body
34
+ *
35
+ * @param $content
36
+ * @param int $tmpl_id
37
+ * @param int $campaign_id
38
+ *
39
+ * @return mixed|string
40
+ *
41
+ * @since 4.0.0
42
+ */
43
  public static function es_process_template_body( $content, $tmpl_id = 0, $campaign_id = 0 ) {
44
  $content = convert_chars( convert_smilies( wptexturize( $content ) ) );
45
  if ( isset( $GLOBALS['wp_embed'] ) ) {
46
  $content = $GLOBALS['wp_embed']->autoembed( $content );
47
  }
48
 
49
+ $content = wpautop( $content );
50
+ $content = do_shortcode( shortcode_unautop( $content ) );
51
+ $data['content'] = $content;
52
+ $data['tmpl_id'] = $tmpl_id;
53
  $data['campaign_id'] = $campaign_id;
54
+ $data = apply_filters( 'es_after_process_template_body', $data );
55
+ $content = $data['content'];
56
  //total contacts
57
  $total_contacts = ES()->contacts_db->count_active_contacts_by_list_id();
58
  $content = str_replace( "{{TOTAL-CONTACTS}}", $total_contacts, $content );
62
  // site url
63
  $site_url = home_url( '/' );
64
  $content = str_replace( "{{SITEURL}}", $site_url, $content );
65
+ //add pre header if available
66
+ $meta = ES()->campaigns_db->get_campaign_meta_by_id( $campaign_id );
67
+
68
+ $meta['pre_header'] = !empty($meta['pre_header']) ? $meta['pre_header'] : '';
69
+ if( !empty( $meta['pre_header'] )){
70
+ $content = '<span class="es_preheader" style="display: none !important; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;">'.$meta['pre_header'].'</span>'.$content;
71
+ }
72
 
73
  return $content;
74
  }
75
 
76
  /**
77
+ * Get Statuses key name map
78
  *
79
+ * @param bool $reverse
80
+ *
81
+ * @return array
82
  *
83
+ * @since 4.0.0
84
  */
 
 
 
 
85
  public static function get_statuses_key_name_map( $reverse = false ) {
86
 
87
  $statuses = array(
 
88
  'subscribed' => __( 'Subscribed', 'email-subscribers' ),
89
  'unconfirmed' => __( 'Unconfirmed', 'email-subscribers' ),
90
+ 'unsubscribed' => __( 'Unsubscribed', 'email-subscribers' )
 
 
91
  );
92
 
93
  if ( $reverse ) {
97
  return $statuses;
98
  }
99
 
100
+ /**
101
+ * Prepare Statuses dropdown
102
+ *
103
+ * @param string $selected
104
+ * @param string $default_label
105
+ *
106
+ * @return string
107
+ *
108
+ * @since 4.0.0
109
+ */
 
110
  public static function prepare_statuses_dropdown_options( $selected = '', $default_label = 'Select Status' ) {
111
 
 
 
 
 
112
  $default_status[0] = __( $default_label, 'email-subscribers' );
113
 
114
  $statuses = self::get_statuses_key_name_map();
128
  return $dropdown;
129
  }
130
 
131
+ /**
132
+ * Prepare list dropdown
133
+ *
134
+ * @param string $selected
135
+ * @param string $default_label
136
+ *
137
+ * @return string
138
+ *
139
+ * @since 4.0.0
140
+ */
141
  public static function prepare_list_dropdown_options( $selected = '', $default_label = 'Select List' ) {
142
 
143
  $default_option[0] = __( $default_label, 'email-subscribers' );
159
  return $dropdown;
160
  }
161
 
162
+ /**
163
+ * @param string $selected
164
+ * @param string $default_label
165
+ *
166
+ * @return string
167
+ *
168
+ * @since 4.2.0
169
+ * @since 4.3.2 Removed $where condition to find forms
170
+ */
171
  public static function prepare_form_dropdown_options( $selected = '', $default_label = 'Select Form' ) {
172
 
173
+ $forms = ES()->forms_db->get_id_name_map();
 
 
174
 
175
  if ( ! is_null( $default_label ) ) {
176
  $default_option[0] = __( $default_label, 'email-subscribers' );
177
+ $forms = $default_option + $forms;
178
  }
179
 
180
  $dropdown = '';
181
+ foreach ( $forms as $key => $form ) {
182
  $dropdown .= "<option value='{$key}'";
183
 
184
  if ( $selected == $key ) {
185
  $dropdown .= "selected = selected";
186
  }
187
 
188
+ $dropdown .= ">{$form}</option>";
189
  }
190
 
191
  return $dropdown;
192
  }
193
 
194
+ /**
195
+ * Generate GUID
196
+ *
197
+ * @param int $length
198
+ *
199
+ * @return string
200
+ *
201
+ * @since 4.0.0
202
+ */
 
 
 
 
 
 
 
 
203
  public static function generate_guid( $length = 6 ) {
204
 
205
  $str = 'abcdefghijklmnopqrstuvwxyz';
213
  return $guid;
214
  }
215
 
216
+ /**
217
+ * Prepare template dropdown options
218
+ *
219
+ * @param string $type
220
+ * @param string $selected
221
+ *
222
+ * @return string
223
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  public static function prepare_templates_dropdown_options( $type = 'newsletter', $selected = '' ) {
225
 
226
  $default_template_option = new stdClass();
253
 
254
  }
255
 
256
+ /**
257
+ * Prepare status dropdown options
258
+ *
259
+ * @param $selected
260
+ *
261
+ * @return string
262
+ *
263
+ * @since 4.0.0
264
+ */
265
  public static function prepare_status_dropdown_options( $selected ) {
266
  $statuses = array(
267
  '1' => __( 'Active', 'email-subscribers' ),
282
  return $dropdown;
283
  }
284
 
285
+ /**
286
+ * Get ES Templates
287
+ *
288
+ * @param string $type
289
+ *
290
+ * @return int[]|WP_Post[]
291
+ *
292
+ * @since 4.0.0
293
+ */
294
  public static function get_templates( $type = 'newsletter' ) {
295
 
296
  $es_args = array(
315
 
316
  }
317
 
318
+ /**
319
+ * Prepare categories checkboxes
320
+ *
321
+ * @param array $category_names
322
+ *
323
+ * @return string
324
+ *
325
+ * @since 4.0.0
326
+ */
327
  public static function prepare_categories_html( $category_names = array() ) {
328
  $categories = get_terms( array(
329
  'taxonomy' => 'category',
336
  $category_html = '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><input class="es-note-category-parent" type="radio" ' . $checked_selected . ' value="selected_cat" name="es_note_cat_parent">' . __( 'Select Categories', 'email-subscribers' ) . '</td></tr>';
337
  foreach ( $categories as $category ) {
338
 
 
 
339
  if ( in_array( $category->term_id, $category_names ) ) {
340
  $checked = "checked='checked'";
341
  } else {
350
  return $all_html . $category_html;
351
  }
352
 
353
+ /**
354
+ * Prepare custom post types checkboxes
355
+ *
356
+ * @param $custom_post_types
357
+ *
358
+ * @return string
359
+ *
360
+ * @since 4.0.0
361
+ */
362
  public static function prepare_custom_post_type_checkbox( $custom_post_types ) {
363
  $args = array( 'public' => true, 'exclude_from_search' => false, '_builtin' => false );
364
  $output = 'names';
383
  return $custom_post_type_html;
384
  }
385
 
386
+ /**
387
+ * Get Opt-in types
388
+ *
389
+ * @return array
390
+ *
391
+ * @since 4.0.0
392
+ */
 
 
 
 
 
393
  public static function get_optin_types() {
394
 
395
  $types = array(
400
  return $types;
401
  }
402
 
403
+ /**
404
+ * Get Image sizes
405
+ *
406
+ * @return array
407
+ *
408
+ * @since 4.0.0
409
+ */
410
  public static function get_image_sizes() {
411
  $sizes = array(
412
  'full' => __( 'Full Size', 'email-subscribers' ),
417
  return $sizes;
418
  }
419
 
420
+ /**
421
+ * Get IG Option
422
+ *
423
+ * @param $option
424
+ * @param null $default
425
+ *
426
+ * @return mixed|void|null
427
+ *
428
+ * @since 4.0.15
429
+ */
430
  public static function get_ig_option( $option, $default = null ) {
431
 
432
  if ( empty( $option ) ) {
439
 
440
  }
441
 
442
+ /**
443
+ * Set ig option
444
+ *
445
+ * @param $option
446
+ * @param $value
447
+ *
448
+ * @return bool|null
449
+ *
450
+ * @since 4.0.15
451
+ */
452
  public static function set_ig_option( $option, $value ) {
453
 
454
  if ( empty( $option ) ) {
480
  return delete_option( $option_prefix . $option );
481
  }
482
 
483
+ /**
484
+ * Convert categories array to string
485
+ *
486
+ * @param array $categories
487
+ *
488
+ * @return string
489
+ *
490
+ * @since 4.0.0
491
+ */
492
  public static function convert_categories_array_to_string( $categories = array() ) {
493
 
494
  $categories_str = '';
501
  return $categories_str;
502
  }
503
 
504
+ /**
505
+ * Convert categories string to array
506
+ *
507
+ * @param string $categories_str
508
+ * @param bool $keep_ids
509
+ *
510
+ * @return array|mixed
511
+ *
512
+ * @since 4.0.0
513
+ */
514
  public static function convert_categories_string_to_array( $categories_str = '', $keep_ids = true ) {
515
  $categories = array();
516
  if ( strlen( $categories_str ) > 0 ) {
526
  return $categories;
527
  }
528
 
529
+ /**
530
+ * Convert Category id to name
531
+ *
532
+ * @param $category
533
+ *
534
+ * @return string
535
+ *
536
+ * @since 4.1.0
537
+ */
538
  public static function convert_id_to_name( $category ) {
539
  if ( $category != 'All' ) {
540
  return get_cat_name( $category );
543
  }
544
  }
545
 
546
+ /**
547
+ * Get category id based on name
548
+ *
549
+ * @param $category
550
+ *
551
+ * @return int|string
552
+ *
553
+ * @since 4.1.0
554
+ */
555
  public static function convert_name_to_id( $category ) {
556
  if ( strpos( $category, '{T}' ) === false ) {
557
  $category = wp_specialchars_decode( addslashes( $category ) );
562
  }
563
  }
564
 
565
+ /**
566
+ * Prepare categories ids string
567
+ *
568
+ * @param string $category
569
+ *
570
+ * @return string
571
+ *
572
+ * @since 4.1.0
573
+ */
574
  public static function prepare_category_string( $category = '' ) {
575
  $category_str = '';
576
  if ( ! empty( $category ) ) {
 
577
  $category_str = "##" . $category . "##";
578
  }
579
 
580
  return $category_str;
581
  }
582
 
583
+ /**
584
+ * Prepare custom post types string
585
+ *
586
+ * @param string $post_type
587
+ *
588
+ * @return string
589
+ *
590
+ * @since 4.1.0
591
+ */
592
  public static function prepare_custom_post_type_string( $post_type = '' ) {
593
  $post_type_str = '';
594
  if ( ! empty( $post_type ) ) {
598
  return $post_type_str;
599
  }
600
 
601
+ /**
602
+ * Convert categories name string into ids string
603
+ *
604
+ * @param $categories_str
605
+ *
606
+ * @return string
607
+ *
608
+ * @since 4.1.0
609
+ */
610
  public static function prepare_categories_migration_string( $categories_str ) {
611
  $categories = self::convert_categories_string_to_array( $categories_str, true );
612
  $categories = array_map( array( 'ES_Common', 'convert_name_to_id' ), $categories );
616
 
617
  }
618
 
619
+ /**
620
+ * Prepare first name & last name from name
621
+ *
622
+ * @param string $name
623
+ *
624
+ * @return array
625
+ *
626
+ * @since 4.0.0
627
+ */
628
  public static function prepare_first_name_last_name( $name = '' ) {
629
  $result = array(
630
  'first_name' => '',
650
  return $result;
651
  }
652
 
653
+ /**
654
+ * Prepare name from first name & last name
655
+ *
656
+ * @param string $first_name
657
+ * @param string $last_name
658
+ *
659
+ * @return string
660
+ *
661
+ * @since 4.0.0
662
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
663
  public static function prepare_name_from_first_name_last_name( $first_name = '', $last_name = '' ) {
664
  $first_name = trim( $first_name );
665
  $last_name = trim( $last_name );
667
  return trim( $first_name . ' ' . $last_name );
668
  }
669
 
670
+ /**
671
+ * Get name from email
672
+ *
673
+ * @param $email
674
+ *
675
+ * @return string
676
+ *
677
+ * @since 4.0.0
678
+ */
679
  public static function get_name_from_email( $email ) {
680
  $name = strstr( $email, '@', true );
681
 
682
  return trim( $name );
683
  }
684
 
 
685
  /**
686
+ * Migrate Older wigets into newer one.
687
  *
688
+ * @since 4.0.5
689
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
690
  public static function migrate_widgets() {
 
691
  /**
692
  * Option - 1 -> ES < 3.x email-subscribers
693
  * Option - 2 -> ES < 4.0.4 email_subscriber_widget
706
  * - Change Option 1 with Option 3
707
  * - Change Option 2 with Option 3
708
  */
 
709
  $es_3_widget_option = 'widget_email-subscribers';
710
  $es_4_widget_option = 'widget_email_subscriber_widget';
711
  $latest_widget_option = 'widget_email-subscribers-form';
833
 
834
  }
835
 
836
+ /**
837
+ * Filter Category
838
+ *
839
+ * @param $category
840
+ *
841
+ * @return string
842
+ *
843
+ * @sinc 4.1.0
844
+ */
845
  public static function temp_filter_category( $category ) {
846
  return trim( trim( $category ), '#' );
847
  }
848
 
849
+ /**
850
+ * Show Message
851
+ *
852
+ * @param string $message
853
+ * @param string $status
854
+ * @param bool $is_dismissible
855
+ *
856
+ * @since 4.1.0
857
+ */
858
  public static function show_message( $message = '', $status = 'success', $is_dismissible = true ) {
859
 
860
  $class = 'notice notice-success';
869
  echo "<div class='{$class}'><p>{$message}</p></div>";
870
  }
871
 
872
+ /**
873
+ * Prepare navigation tabs
874
+ *
875
+ * @param $navigation_tabs
876
+ *
877
+ * @since 4.1.0
878
+ */
879
  public static function prepare_main_header_navigation( $navigation_tabs ) {
880
 
881
  foreach ( $navigation_tabs as $key => $navigation ) {
893
  } ?>"><?php echo $action_label; ?>
894
  <?php if ( $show_indicator ) { ?>
895
  <span class="ig-es-indicator <?php echo $indicator_class; ?>">
896
+ <?php echo $indicator_label ?>
897
+ </span>
898
 
899
  <?php } ?>
900
  </a>
901
  <?php }
902
  }
903
 
904
+ /**
905
+ * Prepare information box to show different kind of information
906
+ * info | warnings | success | error
907
+ *
908
+ * @param $info
909
+ * @param $content_html
910
+ *
911
+ * @since 4.1.0
912
+ */
913
  public static function prepare_information_box( $info, $content_html ) {
914
 
915
  $default_args = array(
962
  *
963
  * @param $params
964
  *
965
+ * @since 4.1.0
966
  */
967
  public static function render_feedback_widget( $params ) {
968
  global $ig_es_feedback;
1030
 
1031
  }
1032
 
1033
+ /**
1034
+ * Get all ES settings
1035
+ *
1036
+ * @return array
1037
+ *
1038
+ * @since 4.1.0
1039
+ */
1040
  public static function get_all_settings() {
1041
 
1042
  global $wpdb;
1055
  return $options_name_value_map;
1056
  }
1057
 
1058
+ /**
1059
+ * Get plugin meta info
1060
+ *
1061
+ * @return array
1062
+ *
1063
+ * @since 4.1.0
1064
+ */
1065
  public static function get_ig_es_meta_info() {
1066
 
1067
  $total_contacts = ES()->contacts_db->count();
1068
  $total_lists = ES()->lists_db->count_lists();
1069
  $total_newsletters = ES()->campaigns_db->get_total_newsletters();
1070
+ $total_post_notifications = ES()->campaigns_db->get_total_post_notifications();
1071
 
1072
  $meta_info = array(
1073
  'total_contacts' => $total_contacts,
1295
 
1296
  return substr( md5( $auth_key . wp_rand( $length, 64 ) ), 0, $length );
1297
  }
 
1298
  }
lite/includes/class-es-install.php CHANGED
@@ -8,10 +8,31 @@ if ( ! class_exists( 'ES_Install' ) ) {
8
  * ES_Install Class.
9
  */
10
  class ES_Install {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
  * DB updates and callbacks that need to be run per version.
13
  *
 
14
  * @var array
 
15
  */
16
  private static $db_updates = array(
17
 
@@ -161,27 +182,13 @@ if ( ! class_exists( 'ES_Install' ) ) {
161
  'ig_es_update_431_disable_autoload_options',
162
  'ig_es_update_431_db_version'
163
  ),
 
 
 
 
164
 
165
  );
166
 
167
- /**
168
- * Background update class.
169
- *
170
- * @var object
171
- */
172
- public static $logger;
173
-
174
- /**
175
- * Added Logger Context
176
- *
177
- * @since 4.2.0
178
- * @var array
179
- *
180
- */
181
- public static $logger_context = array(
182
- 'source' => 'ig_es_db_updates'
183
- );
184
-
185
  /**
186
  * Init Install/ Update Process
187
  *
@@ -302,11 +309,14 @@ if ( ! class_exists( 'ES_Install' ) ) {
302
  self::create_default_form();
303
 
304
  self::$logger->info( 'Create default form.', self::$logger_context );
 
 
 
 
 
305
  self::$logger->info( 'Installation Complete.', self::$logger_context );
306
  }
307
-
308
  self::maybe_update_db_version();
309
-
310
  delete_transient( 'ig_es_installing' );
311
 
312
  }
@@ -658,16 +668,16 @@ if ( ! class_exists( 'ES_Install' ) ) {
658
  $new_contact_email_content = "Hi,\r\n\r\nYour friendly Email Subscribers notification bot here!\r\n\r\n{{NAME}} ({{EMAIL}}) joined our tribe just now.\r\n\r\nWhich list/s? {{LIST}}\r\n\r\nIf you know this person, or if they are an influencer, you may want to reach out to them personally!\r\n\r\nLater...";
659
 
660
  $confirmation_email_subject = "Thanks!";
661
- $confirmation_email_content = "Hi {{NAME}},\r\n\r\nJust one more step before we share the awesomeness from {{SITENAME}}!\r\n\r\nPlease confirm your subscription by clicking on this link:\r\n\r\n{{SUBSCRIBE-LINK}}\r\n\r\nThanks!";
662
 
663
  $welcome_email_subject = "Welcome to {{SITENAME}}";
664
  $welcome_email_content = "Hi {{NAME}},\r\n\r\nJust wanted to send you a quick note...\r\n\r\nThank you for joining the awesome {{SITENAME}} tribe.\r\n\r\nOnly valuable emails from me, promise!\r\n\r\nThanks!";
665
 
666
  $cron_admin_email = "Hi Admin,\r\n\r\nCron URL has been triggered successfully on {{DATE}} for the email '{{SUBJECT}}'. And it sent email to {{COUNT}} recipient(s).\r\n\r\nBest,\r\n" . $blogname;
667
- $unsubscribe_link_content = "I'd be sad to see you go. But if you want to, you can unsubscribe from here: {{UNSUBSCRIBE-LINK}}";
668
 
669
- $unsubscribe_message = "<h2>Unsubscribed.</h2><p>You will no longer hear from us. ☹️ Sorry to see you go!</p>";
670
- $subscription_error_messsage = "Hmm.. Something's amiss..\r\n\r\nCould not complete your request. That email address is probably already subscribed. Or worse blocked!!\r\n\r\nPlease try again after some time - or contact us if the problem persists.\r\n\r\n";
671
 
672
  $unsubscribe_error_message = "Urrgh.. Something's wrong..\r\n\r\nAre you sure that email address is on our file? There was some problem in completing your request.\r\n\r\nPlease try again after some time - or contact us if the problem persists.\r\n\r\n";
673
 
@@ -694,7 +704,7 @@ if ( ! class_exists( 'ES_Install' ) ) {
694
  'ig_es_email_type' => array( 'default' => 'wp_html_mail', 'old_option' => 'ig_es_emailtype', 'action' => 'convert_space_to_underscore' ),
695
  'ig_es_notify_admin' => array( 'default' => 'yes', 'old_option' => 'ig_es_notifyadmin', 'action' => 'convert_space_to_underscore' ),
696
  'ig_es_optin_type' => array( 'default' => 'double_opt_in', 'old_option' => 'ig_es_optintype', 'action' => 'convert_space_to_underscore' ),
697
- 'ig_es_subscription_error_messsage' => array( 'default' => $subscription_error_messsage, 'old_option' => 'ig_es_suberror' ),
698
  'ig_es_subscription_success_message' => array( 'default' => "You have been successfully subscribed.", 'old_option' => 'ig_es_successmsg' ),
699
  'ig_es_unsubscribe_error_message' => array( 'default' => $unsubscribe_error_message, 'old_option' => 'ig_es_unsuberror' ),
700
  'ig_es_unsubscribe_success_message' => array( 'default' => $unsubscribe_message, 'old_option' => 'ig_es_unsubtext' ),
@@ -1128,7 +1138,6 @@ if ( ! class_exists( 'ES_Install' ) ) {
1128
  * - Create Broadcast Campaign
1129
  * - Send Email.
1130
  */
1131
-
1132
  $from_name = ES_Common::get_ig_option( 'from_name' );
1133
  $from_email = ES_Common::get_ig_option( 'from_email' );
1134
 
@@ -1211,20 +1220,24 @@ if ( ! class_exists( 'ES_Install' ) ) {
1211
  $email_created = time();
1212
 
1213
  // Newsletter Send
1214
-
1215
  $email_template = ES_Common::convert_es_templates( $sample, $from_name, $from_email, $email_created );
1216
- $response = ES_Mailer::send( $from_email, $title, $email_template );
1217
- if ( ! empty( $response ) && $response['status'] === 'SUCCESS' ) {
1218
- //update sent details
1219
- $emails = ES_DB_Sending_Queue::get_emails_to_be_sent_by_hash( $guid, 5 );
1220
- $ids = array();
1221
- foreach ( $emails as $email ) {
1222
- $ids[] = $email['id'];
1223
- }
1224
- ES_DB_Sending_Queue::update_sent_status( $ids, 'Sent' );
1225
- ES_DB_Mailing_Queue::update_sent_status( $guid, 'Sent' );
1226
  }
1227
 
 
 
 
 
 
 
1228
  return $response;
1229
  }
1230
 
@@ -1340,21 +1353,25 @@ if ( ! class_exists( 'ES_Install' ) ) {
1340
 
1341
  $email_created = time();
1342
 
1343
- // Post Notification Send Send
1344
  $email_template = ES_Common::convert_es_templates( $content, $from_name, $from_email, $email_created );
1345
- $response = ES_Mailer::send( $from_email, $title, $email_template );
1346
- if ( ! empty( $response ) && $response['status'] === 'SUCCESS' ) {
1347
- //update sent details
1348
- $emails = ES_DB_Sending_Queue::get_emails_to_be_sent_by_hash( $guid, 5 );
1349
- $ids = array();
1350
- foreach ( $emails as $email ) {
1351
- $ids[] = $email['id'];
1352
- }
1353
- ES_DB_Sending_Queue::update_sent_status( $ids, 'Sent' );
1354
- ES_DB_Mailing_Queue::update_sent_status( $guid, 'Sent' );
1355
- //change post notification from test to main
1356
  }
1357
 
 
 
 
 
 
 
1358
  return $response;
1359
  }
1360
  }
@@ -1446,6 +1463,84 @@ if ( ! class_exists( 'ES_Install' ) ) {
1446
  ES()->forms_db->add_form( $form_data );
1447
  }
1448
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1449
  /**
1450
  * Create files/ directory
1451
  *
8
  * ES_Install Class.
9
  */
10
  class ES_Install {
11
+
12
+ /**
13
+ * Background update class.
14
+ *
15
+ * @var object
16
+ */
17
+ public static $logger;
18
+
19
+ /**
20
+ * Added Logger Context
21
+ *
22
+ * @since 4.2.0
23
+ * @var array
24
+ *
25
+ */
26
+ public static $logger_context = array(
27
+ 'source' => 'ig_es_db_updates'
28
+ );
29
+
30
  /**
31
  * DB updates and callbacks that need to be run per version.
32
  *
33
+ * @since 4.0.0
34
  * @var array
35
+ *
36
  */
37
  private static $db_updates = array(
38
 
182
  'ig_es_update_431_disable_autoload_options',
183
  'ig_es_update_431_db_version'
184
  ),
185
+ '4.3.2' => array(
186
+ 'ig_es_update_432_import_bfcm_templates',
187
+ 'ig_es_update_432_db_version'
188
+ )
189
 
190
  );
191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  /**
193
  * Init Install/ Update Process
194
  *
309
  self::create_default_form();
310
 
311
  self::$logger->info( 'Create default form.', self::$logger_context );
312
+
313
+ self::load_templates();
314
+
315
+ self::$logger->info( 'Load readymade template', self::$logger_context );
316
+
317
  self::$logger->info( 'Installation Complete.', self::$logger_context );
318
  }
 
319
  self::maybe_update_db_version();
 
320
  delete_transient( 'ig_es_installing' );
321
 
322
  }
668
  $new_contact_email_content = "Hi,\r\n\r\nYour friendly Email Subscribers notification bot here!\r\n\r\n{{NAME}} ({{EMAIL}}) joined our tribe just now.\r\n\r\nWhich list/s? {{LIST}}\r\n\r\nIf you know this person, or if they are an influencer, you may want to reach out to them personally!\r\n\r\nLater...";
669
 
670
  $confirmation_email_subject = "Thanks!";
671
+ $confirmation_email_content = "Hi {{NAME}},\r\n\r\nJust one more step before we share the awesomeness from {{SITENAME}}!\r\n\r\nPlease confirm your subscription by clicking on <a href='{{SUBSCRIBE-LINK}}'>this link</a>\r\n\r\nThanks!";
672
 
673
  $welcome_email_subject = "Welcome to {{SITENAME}}";
674
  $welcome_email_content = "Hi {{NAME}},\r\n\r\nJust wanted to send you a quick note...\r\n\r\nThank you for joining the awesome {{SITENAME}} tribe.\r\n\r\nOnly valuable emails from me, promise!\r\n\r\nThanks!";
675
 
676
  $cron_admin_email = "Hi Admin,\r\n\r\nCron URL has been triggered successfully on {{DATE}} for the email '{{SUBJECT}}'. And it sent email to {{COUNT}} recipient(s).\r\n\r\nBest,\r\n" . $blogname;
677
+ $unsubscribe_link_content = "I'd be sad to see you go. But if you want to, you can unsubscribe from <a href='{{UNSUBSCRIBE-LINK}}'>here</a>";
678
 
679
+ $unsubscribe_message = "<h2>Unsubscribed.</h2><p>You will no longer hear from us. ☹️ Sorry to see you go!</p>";
680
+ $subscription_error_message = "Hmm.. Something's amiss..\r\n\r\nCould not complete your request. That email address is probably already subscribed. Or worse blocked!!\r\n\r\nPlease try again after some time - or contact us if the problem persists.\r\n\r\n";
681
 
682
  $unsubscribe_error_message = "Urrgh.. Something's wrong..\r\n\r\nAre you sure that email address is on our file? There was some problem in completing your request.\r\n\r\nPlease try again after some time - or contact us if the problem persists.\r\n\r\n";
683
 
704
  'ig_es_email_type' => array( 'default' => 'wp_html_mail', 'old_option' => 'ig_es_emailtype', 'action' => 'convert_space_to_underscore' ),
705
  'ig_es_notify_admin' => array( 'default' => 'yes', 'old_option' => 'ig_es_notifyadmin', 'action' => 'convert_space_to_underscore' ),
706
  'ig_es_optin_type' => array( 'default' => 'double_opt_in', 'old_option' => 'ig_es_optintype', 'action' => 'convert_space_to_underscore' ),
707
+ 'ig_es_subscription_error_messsage' => array( 'default' => $subscription_error_message, 'old_option' => 'ig_es_suberror' ),
708
  'ig_es_subscription_success_message' => array( 'default' => "You have been successfully subscribed.", 'old_option' => 'ig_es_successmsg' ),
709
  'ig_es_unsubscribe_error_message' => array( 'default' => $unsubscribe_error_message, 'old_option' => 'ig_es_unsuberror' ),
710
  'ig_es_unsubscribe_success_message' => array( 'default' => $unsubscribe_message, 'old_option' => 'ig_es_unsubtext' ),
1138
  * - Create Broadcast Campaign
1139
  * - Send Email.
1140
  */
 
1141
  $from_name = ES_Common::get_ig_option( 'from_name' );
1142
  $from_email = ES_Common::get_ig_option( 'from_email' );
1143
 
1220
  $email_created = time();
1221
 
1222
  // Newsletter Send
 
1223
  $email_template = ES_Common::convert_es_templates( $sample, $from_name, $from_email, $email_created );
1224
+
1225
+ $merge_tags = array(
1226
+ 'message_id' => $last_report_id,
1227
+ 'campaign_id' => $campaign_id
1228
+ );
1229
+
1230
+ $emails = array();
1231
+ foreach ( $subscribers as $subscriber ) {
1232
+ $emails[] = $subscriber['email'];
 
1233
  }
1234
 
1235
+ ES_DB_Mailing_Queue::update_sent_status( $guid, 'Sending' );
1236
+
1237
+ $response = ES()->mailer->send( $title, $email_template, $emails, $merge_tags );
1238
+
1239
+ ES_DB_Mailing_Queue::update_sent_status( $guid, 'Sent' );
1240
+
1241
  return $response;
1242
  }
1243
 
1353
 
1354
  $email_created = time();
1355
 
1356
+ // Post Notification Send
1357
  $email_template = ES_Common::convert_es_templates( $content, $from_name, $from_email, $email_created );
1358
+
1359
+ $merge_tags = array(
1360
+ 'message_id' => $last_report_id,
1361
+ 'campaign_id' => $campaign_id
1362
+ );
1363
+
1364
+ $emails = array();
1365
+ foreach ( $subscribers as $subscriber ) {
1366
+ $emails[] = $subscriber['email'];
 
 
1367
  }
1368
 
1369
+ ES_DB_Mailing_Queue::update_sent_status( $guid, 'Sending' );
1370
+
1371
+ $response = ES()->mailer->send( $title, $email_template, $emails, $merge_tags );
1372
+
1373
+ ES_DB_Mailing_Queue::update_sent_status( $guid, 'Sent' );
1374
+
1375
  return $response;
1376
  }
1377
  }
1463
  ES()->forms_db->add_form( $form_data );
1464
  }
1465
 
1466
+ /**
1467
+ * Load readymade templates
1468
+ *
1469
+ * @since 4.3.2
1470
+ */
1471
+ public static function load_templates() {
1472
+ //TODO :: Add template with custom post type
1473
+ global $wpdb;
1474
+
1475
+ $templates = array();
1476
+ $templates = apply_filters( 'ig_es_email_templates', $templates );
1477
+
1478
+ $prefix = $wpdb->prefix;
1479
+ $sSql = "SELECT post_name FROM `" . $prefix . "posts` where post_type = 'es_template'";
1480
+ $imported_templ = $wpdb->get_col( $sSql );
1481
+
1482
+ if ( is_array( $templates ) && count( $templates ) > 0 ) {
1483
+
1484
+ foreach ( $templates as $slug => $template ) {
1485
+ if ( in_array( $slug, $imported_templ ) ) {
1486
+ continue;
1487
+ }
1488
+
1489
+ $es_post = array(
1490
+ 'post_title' => wp_strip_all_tags( $template['es_templ_heading'] ),
1491
+ 'post_content' => $template['es_templ_body'],
1492
+ 'post_status' => 'publish',
1493
+ 'post_type' => 'es_template',
1494
+ 'post_name' => $slug,
1495
+ 'meta_input' => array(
1496
+ 'es_template_type' => $template['es_email_type'],
1497
+ 'es_custom_css' => $template['es_custom_css']
1498
+ )
1499
+ );
1500
+ // Insert the post into the database
1501
+ $last_inserted_id = wp_insert_post( $es_post );
1502
+
1503
+ // Generate Featured Image
1504
+ self::es_generate_featured_image( $template['es_thumbnail'], $last_inserted_id );
1505
+
1506
+ }
1507
+ }
1508
+ }
1509
+
1510
+ /**
1511
+ * Generate Featured Image
1512
+ *
1513
+ * @param $image_url
1514
+ * @param $post_id
1515
+ *
1516
+ * @since 4.3.2
1517
+ */
1518
+ public static function es_generate_featured_image( $image_url, $post_id ) {
1519
+ $upload_dir = wp_upload_dir();
1520
+ $image_data = file_get_contents( $image_url );
1521
+ $filename = basename( $image_url );
1522
+ if ( wp_mkdir_p( $upload_dir['path'] ) ) {
1523
+ $file = $upload_dir['path'] . '/' . $filename;
1524
+ } else {
1525
+ $file = $upload_dir['basedir'] . '/' . $filename;
1526
+ }
1527
+ file_put_contents( $file, $image_data );
1528
+
1529
+ $wp_filetype = wp_check_filetype( $filename, null );
1530
+ $attachment = array(
1531
+ 'post_mime_type' => $wp_filetype['type'],
1532
+ 'post_title' => sanitize_file_name( $filename ),
1533
+ 'post_content' => '',
1534
+ 'post_status' => 'inherit'
1535
+ );
1536
+ $attach_id = wp_insert_attachment( $attachment, $file, $post_id );
1537
+ require_once( ABSPATH . 'wp-admin/includes/image.php' );
1538
+ $attach_data = wp_generate_attachment_metadata( $attach_id, $file );
1539
+ $res1 = wp_update_attachment_metadata( $attach_id, $attach_data );
1540
+ $res2 = set_post_thumbnail( $post_id, $attach_id );
1541
+ }
1542
+
1543
+
1544
  /**
1545
  * Create files/ directory
1546
  *
lite/includes/classes/class-es-actions.php ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ if ( ! class_exists( 'ES_Actions' ) ) {
8
+ /**
9
+ * Class ES_Actions
10
+ *
11
+ * Track all actions
12
+ *
13
+ * IG_CONTACT_SUBSCRIBE => 1,
14
+ * IG_MESSAGE_SENT => 2,
15
+ * IG_MESSAGE_OPEN => 3,
16
+ * IG_LINK_CLICK => 4,
17
+ * IG_CONTACT_UNSUBSCRIBE => 5,
18
+ * IG_MESSAGE_SOFT_BOUNCE => 6,
19
+ * IG_MESSAGE_HARD_BOUNCE => 7,
20
+ * IG_MESSAGE_ERROR => 8
21
+ *
22
+ * @since 4.2.0
23
+ */
24
+ class ES_Actions {
25
+ /**
26
+ * ES_DB_Actions object
27
+ *
28
+ * @since 4.2.1
29
+ * @var $db
30
+ *
31
+ */
32
+ protected $db;
33
+
34
+ /**
35
+ * ES_Actions constructor.
36
+ *
37
+ * @since 4.2.0
38
+ */
39
+ public function __construct() {
40
+
41
+ $this->db = new ES_DB_Actions();
42
+
43
+ add_action( 'init', array( &$this, 'init' ), 1 );
44
+ }
45
+
46
+ /**
47
+ * Init Actions
48
+ */
49
+ public function init() {
50
+ /**
51
+ * @since 4.2.0
52
+ */
53
+ add_action( 'ig_es_contact_subscribe', array( &$this, 'subscribe' ), 10, 2 );
54
+ add_action( 'ig_es_message_sent', array( &$this, 'sent' ), 10, 3 );
55
+ add_action( 'ig_es_message_open', array( &$this, 'open' ), 10, 3 );
56
+ add_action( 'ig_es_message_click', array( &$this, 'click' ), 10, 5 );
57
+ add_action( 'ig_es_contact_unsubscribe', array( &$this, 'unsubscribe' ), 10, 4 );
58
+ //add_action( 'ig_es_message_bounce', array( &$this, 'bounce' ), 10, 3 );
59
+ //add_action( 'ig_es_subscriber_error', array( &$this, 'error' ), 10, 3 );
60
+ //add_action( 'ig_es_contact_list_unsubscribe', array( &$this, 'list_unsubscribe' ), 10, 4 );
61
+ }
62
+
63
+ /**
64
+ * Get action data
65
+ *
66
+ * @since 4.2.0
67
+ */
68
+ public function get_fields( $fields = null, $where = null ) {
69
+
70
+ global $wpdb;
71
+
72
+ $fields = esc_sql( is_null( $fields ) ? '*' : ( is_array( $fields ) ? implode( ', ', $fields ) : $fields ) );
73
+
74
+ $sql = "SELECT $fields FROM {$wpdb->prefix}ig_actions WHERE 1=1";
75
+ if ( is_array( $where ) ) {
76
+ foreach ( $where as $key => $value ) {
77
+ $sql .= ', ' . esc_sql( $key ) . " = '" . esc_sql( $value ) . "'";
78
+ }
79
+ }
80
+
81
+ return $wpdb->get_results( $sql, ARRAY_A );
82
+
83
+ }
84
+
85
+ /**
86
+ * Add action
87
+ *
88
+ * @param $args
89
+ * @param bool $explicit
90
+ *
91
+ * @return bool
92
+ *
93
+ * @since 4.2.0
94
+ */
95
+ private function add( $args, $explicit = true ) {
96
+
97
+ $args = wp_parse_args( $args, array(
98
+ 'created_at' => ig_es_get_current_gmt_timestamp(),
99
+ 'updated_at' => ig_es_get_current_gmt_timestamp(),
100
+ 'count' => 1,
101
+ ) );
102
+
103
+ return $this->db->add( $args, $explicit );
104
+
105
+ }
106
+
107
+ /**
108
+ * Track Contact Action
109
+ *
110
+ * @param $args
111
+ * @param bool $explicit
112
+ *
113
+ * @since 4.2.4
114
+ */
115
+ private function add_contact_action( $args, $explicit = true ) {
116
+
117
+ return $this->add( $args, $explicit );
118
+ }
119
+
120
+ /**
121
+ * Add action
122
+ *
123
+ * @param $args
124
+ * @param bool $explicit
125
+ *
126
+ * @return bool
127
+ *
128
+ * @since 4.2.0
129
+ */
130
+ private function add_action( $args, $explicit = true ) {
131
+ return $this->add( $args, $explicit );
132
+ }
133
+
134
+ /**
135
+ * Track Subscribe Action
136
+ *
137
+ * @param $contact_id
138
+ * @param array $list_ids
139
+ *
140
+ * @since 4.2.0
141
+ */
142
+ public function subscribe( $contact_id, $list_ids = array() ) {
143
+ if ( is_array( $list_ids ) && count( $list_ids ) > 0 ) {
144
+ foreach ( $list_ids as $list_id ) {
145
+ $this->add_action( array(
146
+ 'contact_id' => $contact_id,
147
+ 'list_id' => $list_id,
148
+ 'type' => IG_CONTACT_SUBSCRIBE
149
+ ) );
150
+ }
151
+ }
152
+
153
+ }
154
+
155
+ /**
156
+ * Track Send Action
157
+ *
158
+ * @param $contact_id
159
+ * @param $message_id
160
+ * @param $campaign_id
161
+ *
162
+ * @return bool
163
+ *
164
+ * @since 4.2.0
165
+ */
166
+ public function sent( $contact_id, $campaign_id = 0, $message_id = 0 ) {
167
+ return $this->add_action( array(
168
+ 'contact_id' => $contact_id,
169
+ 'campaign_id' => $campaign_id,
170
+ 'message_id' => $message_id,
171
+ 'type' => IG_MESSAGE_SENT,
172
+ ) );
173
+ }
174
+
175
+ /**
176
+ * Track Message Open Action
177
+ *
178
+ * @param $contact_id
179
+ * @param $message_id
180
+ * @param $campaign_id
181
+ *
182
+ * @return bool
183
+ *
184
+ * @since 4.2.0
185
+ */
186
+ public function open( $contact_id, $message_id, $campaign_id, $explicit = true ) {
187
+
188
+ // Track only if campaign sent.
189
+ if ( $this->is_campaign_sent( $contact_id, $message_id, $campaign_id ) ) {
190
+
191
+ return $this->add_action( array(
192
+ 'contact_id' => $contact_id,
193
+ 'message_id' => $message_id,
194
+ 'campaign_id' => $campaign_id,
195
+ 'type' => IG_MESSAGE_OPEN,
196
+ ), $explicit );
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Track Link Click Action
202
+ *
203
+ * @param $contact_id
204
+ * @param $message_id
205
+ * @param $campaign_id
206
+ * @param $link_id
207
+ *
208
+ * @return bool
209
+ *
210
+ * @since 4.2.0
211
+ */
212
+ public function click( $link_id, $contact_id, $message_id, $campaign_id, $explicit = true ) {
213
+
214
+ // When someone click on link which means they have opened that email
215
+ // Track Email Open
216
+ $this->open( $contact_id, $message_id, $campaign_id, false );
217
+
218
+ return $this->add_contact_action( array(
219
+ 'contact_id' => $contact_id,
220
+ 'campaign_id' => $campaign_id,
221
+ 'message_id' => $message_id,
222
+ 'link_id' => $link_id,
223
+ 'type' => IG_LINK_CLICK,
224
+ ), $explicit );
225
+ }
226
+
227
+ /**
228
+ * Track Contact Unsubscribe Action
229
+ *
230
+ * @param $contact_id
231
+ * @param $message_id
232
+ * @param $campaign_id
233
+ * @param array $list_ids
234
+ *
235
+ * @since 4.2.0
236
+ */
237
+ public function unsubscribe( $contact_id, $message_id, $campaign_id, $list_ids = array() ) {
238
+ if ( is_array( $list_ids ) && count( $list_ids ) > 0 ) {
239
+ foreach ( $list_ids as $list_id ) {
240
+
241
+ $this->add_action( array(
242
+ 'contact_id' => $contact_id,
243
+ 'message_id' => $message_id,
244
+ 'campaign_id' => $campaign_id,
245
+ 'list_id' => $list_id,
246
+ 'type' => IG_CONTACT_UNSUBSCRIBE,
247
+ ) );
248
+ }
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Track Message Bounce Action
254
+ *
255
+ * @param $contact_id
256
+ * @param $message_id
257
+ * @param $campaign_id
258
+ * @param bool $hard
259
+ *
260
+ * @since 4.2.0
261
+ */
262
+ public function bounce( $contact_id, $campaign_id, $hard = false ) {
263
+ $this->add_action( array(
264
+ 'contact_id' => $contact_id,
265
+ 'campaign_id' => $campaign_id,
266
+ 'type' => $hard ? IG_MESSAGE_HARD_BOUNCE : IG_MESSAGE_SOFT_BOUNCE,
267
+ ) );
268
+ }
269
+
270
+ /**
271
+ * Check whether campaign is sent to specific contact
272
+ *
273
+ * @param $contact_id
274
+ * @param $message_id
275
+ * @param $campaign_id
276
+ *
277
+ * @return string|null
278
+ *
279
+ * @since 4.2.3
280
+ */
281
+ public function is_campaign_sent( $contact_id, $message_id, $campaign_id ) {
282
+
283
+ global $wpdb;
284
+
285
+ $ig_actions_table = IG_ACTIONS_TABLE;
286
+
287
+ $sql = "SELECT count(*) FROM $ig_actions_table WHERE contact_id = %d AND message_id = %d AND campaign_id = %d AND type = %d";
288
+
289
+ return $wpdb->get_var( $wpdb->prepare( $sql, $contact_id, $message_id, $campaign_id, IG_MESSAGE_SENT ) );
290
+ }
291
+ }
292
+ }
293
+
294
+
lite/includes/classes/class-es-admin-settings.php ADDED
@@ -0,0 +1,794 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * The admin-specific functionality of the plugin.
10
+ *
11
+ * Admin Settings
12
+ *
13
+ * @package Email_Subscribers
14
+ * @subpackage Email_Subscribers/admin
15
+ * @author Your Name <email@example.com>
16
+ */
17
+ class ES_Admin_Settings {
18
+
19
+ static $instance;
20
+
21
+ public $subscribers_obj;
22
+
23
+ public function __construct() {
24
+ }
25
+
26
+ public static function set_screen( $status, $option, $value ) {
27
+ return $value;
28
+ }
29
+
30
+ public function es_settings_callback() {
31
+
32
+ $submitted = ig_es_get_request_data( 'submitted' );
33
+ $submit_action = ig_es_get_request_data( 'submit_action' );
34
+
35
+ if ( 'submitted' === $submitted && 'ig-es-save-admin-settings' === $submit_action ) {
36
+
37
+ $nonce = ig_es_get_request_data( 'update-settings' );
38
+ if ( ! wp_verify_nonce( $nonce, 'update-settings' ) ) {
39
+ $message = __( 'You do not have permission to update settings', 'email-subscribers' );
40
+ ES_Common::show_message( $message, 'error' );
41
+ } else {
42
+
43
+ $options = ig_es_get_post_data( '', '', false );
44
+
45
+ $options = apply_filters( 'ig_es_before_save_settings', $options );
46
+
47
+ $options['ig_es_disable_wp_cron'] = isset( $options['ig_es_disable_wp_cron'] ) ? $options['ig_es_disable_wp_cron'] : 'no';
48
+ $options['ig_es_track_email_opens'] = isset( $options['ig_es_track_email_opens'] ) ? $options['ig_es_track_email_opens'] : 'no';
49
+
50
+ $text_fields_to_sanitize = array(
51
+ 'ig_es_from_name',
52
+ 'ig_es_admin_emails',
53
+ 'ig_es_email_type',
54
+ 'ig_es_optin_type',
55
+ 'ig_es_post_image_size',
56
+ 'ig_es_track_email_opens',
57
+ 'ig_es_enable_welcome_email',
58
+ 'ig_es_welcome_email_subject',
59
+ 'ig_es_confirmation_mail_subject',
60
+ 'ig_es_notify_admin',
61
+ 'ig_es_admin_new_contact_email_subject',
62
+ 'ig_es_enable_cron_admin_email',
63
+ 'ig_es_cron_admin_email_subject',
64
+ 'ig_es_cronurl',
65
+ 'ig_es_hourly_email_send_limit',
66
+ 'ig_es_disable_wp_cron'
67
+ );
68
+
69
+ $texarea_fields_to_sanitize = array(
70
+ 'ig_es_unsubscribe_link_content',
71
+ 'ig_es_subscription_success_message',
72
+ 'ig_es_subscription_error_messsage',
73
+ 'ig_es_unsubscribe_success_message',
74
+ 'ig_es_unsubscribe_error_message',
75
+ 'ig_es_welcome_email_content',
76
+ 'ig_es_confirmation_mail_content',
77
+ 'ig_es_admin_new_contact_email_content',
78
+ 'ig_es_cron_admin_email',
79
+ 'ig_es_blocked_domains',
80
+ 'ig_es_form_submission_success_message'
81
+ );
82
+
83
+ $email_fields_to_sanitize = array(
84
+ 'ig_es_from_email'
85
+ );
86
+
87
+ foreach ( $options as $key => $value ) {
88
+ if ( substr( $key, 0, 6 ) === 'ig_es_' ) {
89
+
90
+ $value = stripslashes_deep( $value );
91
+
92
+ if ( in_array( $key, $text_fields_to_sanitize ) ) {
93
+ $value = sanitize_text_field( $value );
94
+ } elseif ( in_array( $key, $texarea_fields_to_sanitize ) ) {
95
+ $value = wp_kses_post( $value );
96
+ } elseif ( in_array( $key, $email_fields_to_sanitize ) ) {
97
+ $value = sanitize_email( $value );
98
+ }
99
+
100
+ update_option( $key, wp_unslash( $value ), false );
101
+ }
102
+ }
103
+
104
+ do_action( 'ig_es_after_settings_save', $options );
105
+
106
+ $message = __( 'Settings have been saved successfully!' );
107
+ $status = 'success';
108
+ ES_Common::show_message( $message, $status );
109
+ }
110
+
111
+ }
112
+
113
+
114
+ ?>
115
+
116
+ <div class="wrap essettings">
117
+ <h1 class="wp-heading-inline">Settings</h1>
118
+ <form action="" method="post" id="email_tabs_form" class="ig-settings-form rcorners">
119
+
120
+ <?php settings_fields( 'email_subscribers_settings' );
121
+ $es_settings_tabs = array(
122
+ 'general' => array( 'icon' => 'admin-generic', 'name' => __( 'General', 'email-subscribers' ) ),
123
+ 'signup_confirmation' => array( 'icon' => 'groups', 'name' => __( 'Notifications', 'email-subscribers' ) ),
124
+ 'email_sending' => array( 'icon' => 'schedule', 'name' => __( 'Email Sending', 'email-subscribers' ) ),
125
+ 'security_settings' => array( 'icon' => 'lock', 'name' => __( 'Security', 'email-subscribers' ) ),
126
+ );
127
+ $es_settings_tabs = apply_filters( 'ig_es_settings_tabs', $es_settings_tabs );
128
+ ?>
129
+
130
+ <div id="es-settings-tabs">
131
+ <div id="menu-tab-listing" class="">
132
+ <ul class="main-tab-nav">
133
+ <?php
134
+ foreach ( $es_settings_tabs as $key => $value ) {
135
+ ?>
136
+ <li class="ig-menu-tab"><a href="#tabs-<?php echo $key ?>"><i class="dashicons dashicons-<?php echo $value['icon'] ?>"></i>&nbsp;<?php echo $value['name'] ?></a></li>
137
+ <?php
138
+ }
139
+ ?>
140
+ </ul>
141
+ </div>
142
+ <div id="menu-tab-content">
143
+ <?php $settings = self::get_registered_settings();
144
+ foreach ( $settings as $key => $value ) {
145
+ ?>
146
+ <div id="tabs-<?php echo $key ?>"><?php $this->render_settings_fields( $value ); ?></div>
147
+ <?php
148
+ }
149
+ ?>
150
+ </div>
151
+
152
+ </div>
153
+ </form>
154
+ </div>
155
+ <?php
156
+
157
+ }
158
+
159
+ public function es_roles_sanitize_options( $input ) {
160
+ $input['option_display_mode'] = wp_filter_nohtml_kses( $input['option_display_mode'] );
161
+ $input['option_font_size'] = sanitize_text_field( absint( $input['option_font_size'] ) );
162
+ $input['option_font_color'] = sanitize_text_field( $input['option_font_color'] );
163
+ $input['option_custom_css'] = esc_textarea( $input['option_custom_css'] );
164
+
165
+ return $input;
166
+ }
167
+
168
+ public static function get_registered_settings() {
169
+
170
+ $general_settings = array(
171
+
172
+ 'sender_information' => array(
173
+ 'id' => 'sender_information',
174
+ 'name' => __( 'Sender', 'email-subscribers' ),
175
+ 'sub_fields' => array(
176
+ 'from_name' => array(
177
+ 'id' => 'ig_es_from_name',
178
+ 'name' => __( 'Name', 'email-subscribers' ),
179
+ 'desc' => __( 'Choose a FROM name for all the emails to be sent from this plugin.', 'email-subscribers' ),
180
+ 'type' => 'text',
181
+ 'placeholder' => __( 'Name', 'email-subscribers' ),
182
+ 'default' => ''
183
+ ),
184
+
185
+ 'from_email' => array(
186
+ 'id' => 'ig_es_from_email',
187
+ 'name' => __( 'Email', 'email-subscribers' ),
188
+ 'desc' => __( 'Choose a FROM email address for all the emails to be sent from this plugin', 'email-subscribers' ),
189
+ 'type' => 'text',
190
+ 'placeholder' => __( 'Email Address', 'email-subscribers' ),
191
+ 'default' => ''
192
+ ),
193
+ )
194
+ ),
195
+
196
+ 'admin_email' => array(
197
+ 'id' => 'ig_es_admin_emails',
198
+ 'name' => __( 'Email Addresses', 'email-subscribers' ),
199
+ 'type' => 'text',
200
+ 'desc' => __( 'Enter the admin email addresses that should receive notifications (separated by comma).', 'email-subscribers' ),
201
+ 'default' => ''
202
+ ),
203
+
204
+ 'ig_es_optin_type' => array(
205
+ 'id' => 'ig_es_optin_type',
206
+ 'name' => __( 'Opt-in Type', 'email-subscribers' ),
207
+ 'desc' => '',
208
+ 'type' => 'select',
209
+ 'options' => ES_Common::get_optin_types(),
210
+ 'default' => ''
211
+ ),
212
+
213
+ 'ig_es_post_image_size' => array(
214
+ 'id' => 'ig_es_post_image_size',
215
+ 'name' => __( 'Image Size', 'email-subscribers' ),
216
+ 'type' => 'select',
217
+ 'options' => ES_Common::get_image_sizes(),
218
+ 'desc' => __( '<p>Select image size for {{POSTIMAGE}} to be shown in the Post Notification Emails.</p>', 'email-subscribers' ),
219
+ 'default' => 'full'
220
+ ),
221
+
222
+ 'ig_es_track_email_opens' => array(
223
+ 'id' => 'ig_es_track_email_opens',
224
+ 'name' => __( 'Track Opens', 'email-subscribers' ),
225
+ 'type' => 'checkbox',
226
+ 'desc' => __( 'Check this if you want to track email opening.', 'email-subscribers' ),
227
+ 'default' => 'yes'
228
+ ),
229
+
230
+ 'ig_es_form_submission_success_message' => array(
231
+ 'type' => 'textarea',
232
+ 'options' => false,
233
+ 'placeholder' => '',
234
+ 'supplemental' => '',
235
+ 'default' => '',
236
+ 'id' => 'ig_es_form_submission_success_message',
237
+ 'name' => __( 'Message to display after form submission', 'email-subscribers' ),
238
+ 'desc' => '',
239
+ ),
240
+ 'ig_es_unsubscribe_link_content' => array(
241
+ 'type' => 'textarea',
242
+ 'options' => false,
243
+ 'placeholder' => '',
244
+ 'supplemental' => '',
245
+ 'default' => '',
246
+ 'id' => 'ig_es_unsubscribe_link_content',
247
+ 'name' => __( 'Show Unsubscribe Message In Email Footer', 'email-subscribers' ),
248
+ 'desc' => __( 'Add text which you want your contact to see in footer to unsubscribe. Use {{UNSUBSCRIBE-LINK}} keyword to add unsubscribe link.', 'email-subscribers' ),
249
+ ),
250
+
251
+ //'ig_es_optin_link' => array( 'type' => 'text', 'options' => false, 'readonly' => 'readonly', 'placeholder' => '', 'supplemental' => '', 'default' => '', 'id' => 'ig_es_optin_link', 'name' => 'Double Opt-In Confirmation Link', 'desc' => '', ),
252
+
253
+ 'subscription_messages' => array(
254
+ 'id' => 'subscription_messages',
255
+ 'name' => __( 'Subscription Success/ Error Messages', 'email-subscribers' ),
256
+ 'sub_fields' => array(
257
+ 'ig_es_subscription_success_message' => array(
258
+ 'type' => 'textarea',
259
+ 'options' => false,
260
+ 'placeholder' => '',
261
+ 'supplemental' => '',
262
+ 'default' => __( 'You have been subscribed successfully!', 'email-subscribers' ),
263
+ 'id' => 'ig_es_subscription_success_message',
264
+ 'name' => __( 'Success Message', 'email-subscribers' ),
265
+ 'desc' => __( 'Show this message if contact is successfully subscribed from Double Opt-In (Confirmation) Email', 'email-subscribers' )
266
+ ),
267
+
268
+ 'ig_es_subscription_error_messsage' => array(
269
+ 'type' => 'textarea',
270
+ 'options' => false,
271
+ 'placeholder' => '',
272
+ 'supplemental' => '',
273
+ 'default' => __( 'Oops.. Your request couldn\'t be completed. This email address seems to be already subscribed / blocked.', 'email-subscribers' ),
274
+ 'id' => 'ig_es_subscription_error_messsage',
275
+ 'name' => __( 'Error Message', 'email-subscribers' ),
276
+ 'desc' => __( 'Show this message if any error occured after clicking confirmation link from Double Opt-In (Confirmation) Email.', 'email-subscribers' )
277
+ ),
278
+
279
+ )
280
+ ),
281
+
282
+ 'unsubscription_messages' => array(
283
+ 'id' => 'unsubscription_messages',
284
+ 'name' => __( 'Unsubscribe Success/ Error Messages', 'email-subscribers' ),
285
+ 'sub_fields' => array(
286
+
287
+ 'ig_es_unsubscribe_success_message' => array(
288
+ 'type' => 'textarea',
289
+ 'options' => false,
290
+ 'placeholder' => '',
291
+ 'supplemental' => '',
292
+ 'default' => __( 'Thank You, You have been successfully unsubscribed. You will no longer hear from us.', 'email-subscribers' ),
293
+ 'id' => 'ig_es_unsubscribe_success_message',
294
+ 'name' => __( 'Success Message', 'email-subscribers' ),
295
+ 'desc' => __( 'Once contact clicks on unsubscribe link, he/she will be redirected to a page where this message will be shown.', 'email-subscribers' )
296
+ ),
297
+
298
+
299
+ 'ig_es_unsubscribe_error_message' => array(
300
+ 'type' => 'textarea',
301
+ 'options' => false,
302
+ 'placeholder' => '',
303
+ 'supplemental' => '',
304
+ 'default' => 'Oops.. There was some technical error. Please try again later or contact us.',
305
+ 'id' => 'ig_es_unsubscribe_error_message',
306
+ 'name' => __( 'Error Message', 'email-subscribers' ),
307
+ 'desc' => __( 'Show this message if any error occured after clicking on unsubscribe link.', 'email-subscribers' )
308
+ )
309
+ )
310
+ ),
311
+
312
+
313
+ /*
314
+ 'sent_report_subject' => array(
315
+ 'id' => 'ig_es_sent_report_subject',
316
+ 'name' => __( 'Sent Report Subject', 'email-subscribers' ),
317
+ 'type' => 'text',
318
+ 'desc' => __( 'Subject for the email report which will be sent to admin.', 'email-subscribers' ),
319
+ 'default' => 'Your email has been sent'
320
+ ),
321
+
322
+ 'sent_report_content' => array(
323
+ 'id' => 'ig_es_sent_report_content',
324
+ 'name' => __( 'Sent Report Content', 'email-subscribers' ),
325
+ 'type' => 'textarea',
326
+ 'desc' => __( 'Content for the email report which will be sent to admin.</p><p>Available Keywords: {{COUNT}}, {{UNIQUE}}, {{STARTTIME}}, {{ENDTIME}}', 'email-subscribers' ),
327
+ ),
328
+ */
329
+ );
330
+
331
+ $general_settings = apply_filters( 'ig_es_registered_general_settings', $general_settings );
332
+
333
+ $signup_confirmation_settings = array(
334
+
335
+ 'welcome_emails' => array(
336
+ 'id' => 'welcome_emails',
337
+ 'name' => __( 'Welcome Email', 'email-subscribers' ),
338
+ 'sub_fields' => array(
339
+
340
+ 'ig_es_enable_welcome_email' => array(
341
+ 'type' => 'select',
342
+ 'options' => array( 'yes' => __( 'Yes', 'email-subscribers' ), 'no' => __( 'No', 'email-subscribers' ) ),
343
+ 'placeholder' => '',
344
+ 'supplemental' => '',
345
+ 'default' => 'yes',
346
+ 'id' => 'ig_es_enable_welcome_email',
347
+ 'name' => __( 'Enable?', 'email-subscribers' ),
348
+ 'desc' => __( 'Send welcome email to new contact after signup.', 'email-subscribers' ),
349
+ ),
350
+
351
+ 'ig_es_welcome_email_subject' => array(
352
+ 'type' => 'text',
353
+ 'options' => false,
354
+ 'placeholder' => '',
355
+ 'supplemental' => '',
356
+ 'default' => '',
357
+ 'id' => 'ig_es_welcome_email_subject',
358
+ 'name' => __( 'Subject', 'email-subscribers' ),
359
+ 'desc' => '',
360
+ ),
361
+ 'ig_es_welcome_email_content' => array(
362
+ 'type' => 'textarea',
363
+ 'options' => false,
364
+ 'placeholder' => '',
365
+ 'supplemental' => '',
366
+ 'default' => '',
367
+ 'id' => 'ig_es_welcome_email_content',
368
+ 'name' => __( 'Content', 'email-subscribers' ),
369
+ 'desc' => __( 'Available keywords. {{FIRSTNAME}}, {{LASTNAME}}, {{NAME}}, {{EMAIL}}, {{LIST}}, {{UNSUBSCRIBE-LINK}}', 'email-subscribers' ),
370
+ ),
371
+ )
372
+ ),
373
+
374
+ 'confirmation_notifications' => array(
375
+ 'id' => 'confirmation_notifications',
376
+ 'name' => __( 'Confirmation Email', 'email-subscribers' ),
377
+ 'sub_fields' => array(
378
+
379
+ 'ig_es_confirmation_mail_subject' => array(
380
+ 'type' => 'text',
381
+ 'options' => false,
382
+ 'placeholder' => '',
383
+ 'supplemental' => '',
384
+ 'default' => '',
385
+ 'id' => 'ig_es_confirmation_mail_subject',
386
+ 'name' => __( 'Subject', 'email-subscribers' ),
387
+ 'desc' => '',
388
+ ),
389
+
390
+ 'ig_es_confirmation_mail_content' => array(
391
+ 'type' => 'textarea',
392
+ 'options' => false,
393
+ 'placeholder' => '',
394
+ 'supplemental' => '',
395
+ 'default' => '',
396
+ 'id' => 'ig_es_confirmation_mail_content',
397
+ 'name' => __( 'Content', 'email-subscribers' ),
398
+ 'desc' => __( 'If Double Optin is set, contact will receive confirmation email with above content. You can use {{FIRSTNAME}}, {{LASTNAME}}, {{NAME}}, {{EMAIL}}, {{SUBSCRIBE-LINK}} keywords', 'email-subscribers' ),
399
+ )
400
+ )
401
+ ),
402
+
403
+ 'admin_notifications' => array(
404
+
405
+ 'id' => 'admin_notifications',
406
+ 'name' => __( 'Admin Notification On New Subscription', 'email-subscribers' ),
407
+ 'sub_fields' => array(
408
+
409
+ 'notify_admin' => array(
410
+ 'id' => 'ig_es_notify_admin',
411
+ 'name' => __( 'Notify?', 'email-subscribers' ),
412
+ 'type' => 'select',
413
+ 'options' => array(
414
+ 'yes' => __( 'Yes', 'email-subscribers' ),
415
+ 'no' => __( 'No', 'email-subscribers' )
416
+ ),
417
+ 'desc' => __( 'Set this option to "Yes" to notify admin(s) for new contact signup.', 'email-subscribers' ),
418
+ 'default' => 'yes'
419
+ ),
420
+
421
+
422
+ 'new_contact_email_subject' => array(
423
+ 'id' => 'ig_es_admin_new_contact_email_subject',
424
+ 'name' => __( 'Subject', 'email-subscribers' ),
425
+ 'type' => 'text',
426
+ 'desc' => __( 'Subject for the admin email whenever a new contact signs up and is confirmed', 'email-subscribers' ),
427
+ 'default' => __( 'New email subscription', 'email-subscribers' )
428
+ ),
429
+
430
+ 'new_contact_email_content' => array(
431
+ 'id' => 'ig_es_admin_new_contact_email_content',
432
+ 'name' => __( 'Content', 'email-subscribers' ),
433
+ 'type' => 'textarea',
434
+ 'desc' => __( 'Content for the admin email whenever a new subscriber signs up and is confirmed. Available Keywords: {{NAME}}, {{EMAIL}}, {{LIST}}', 'email-subscribers' ),
435
+ 'default' => '',
436
+ ),
437
+ )
438
+ ),
439
+
440
+ 'ig_es_cron_report' => array(
441
+ 'id' => 'ig_es_cron_report',
442
+ 'name' => __( 'Admin Notification On Every Campaign Sent', 'email-subscribers' ),
443
+ 'sub_fields' => array(
444
+
445
+ 'ig_es_enable_cron_admin_email' => array(
446
+ 'id' => 'ig_es_enable_cron_admin_email',
447
+ 'name' => __( 'Notify?', 'email-subscribers' ),
448
+ 'type' => 'select',
449
+ 'options' => array(
450
+ 'yes' => __( 'Yes', 'email-subscribers' ),
451
+ 'no' => __( 'No', 'email-subscribers' )
452
+ ),
453
+ 'desc' => __( 'Set this option to "Yes" to notify admin(s) on every campaign sent.', 'email-subscribers' ),
454
+ 'default' => 'yes'
455
+ ),
456
+ 'ig_es_cron_admin_email_subject' => array(
457
+ 'type' => 'text',
458
+ 'options' => false,
459
+ 'placeholder' => '',
460
+ 'supplemental' => '',
461
+ 'default' => __( 'Campaign Sent!', 'email-subscribers' ),
462
+ 'id' => 'ig_es_cron_admin_email_subject',
463
+ 'name' => __( 'Subject', 'email-subscribers' ),
464
+ 'desc' => '',
465
+ ),
466
+
467
+ 'ig_es_cron_admin_email' => array(
468
+ 'type' => 'textarea',
469
+ 'options' => false,
470
+ 'placeholder' => '',
471
+ 'supplemental' => '',
472
+ 'default' => '',
473
+ 'id' => 'ig_es_cron_admin_email',
474
+ 'name' => __( 'Content', 'email-subscribers' ),
475
+ 'desc' => __( 'Send report to admin(s) whenever campaign is successfully sent to all contacts. Available Keywords: {{DATE}}, {{SUBJECT}}, {{COUNT}}', 'email-subscribers' ),
476
+ )
477
+
478
+ )
479
+ )
480
+ );
481
+
482
+ $signup_confirmation_settings = apply_filters( 'ig_es_registered_signup_confirmation_settings', $signup_confirmation_settings );
483
+
484
+ $email_sending_settings = array(
485
+ 'ig_es_cronurl' => array(
486
+ 'type' => 'text',
487
+ 'placeholder' => '',
488
+ 'supplemental' => '',
489
+ 'default' => '',
490
+ 'readonly' => 'readonly',
491
+ 'id' => 'ig_es_cronurl',
492
+ 'name' => __( 'Cron URL', 'email-subscribers' ),
493
+ 'desc' => __( sprintf( __( "You need to visit this URL to send email notifications. Know <a href='%s' target='_blank'>how to run this in background</a>", 'email-subscribers' ),
494
+ "https://www.icegram.com/documentation/es-how-to-schedule-cron-emails-in-cpanel/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page" ) )
495
+ ),
496
+ 'ig_es_disable_wp_cron' => array(
497
+ 'type' => 'checkbox',
498
+ 'placeholder' => '',
499
+ 'supplemental' => '',
500
+ 'default' => 'no',
501
+ 'id' => 'ig_es_disable_wp_cron',
502
+ 'name' => __( 'Disable WordPress Cron', 'email-subscribers' ),
503
+ 'desc' => __( 'Check this if you do not want Email Subscribers to use WP cron for sending emails', 'email-subscribers' )
504
+ ),
505
+
506
+ 'ig_es_hourly_email_send_limit' => array(
507
+ 'type' => 'number',
508
+ 'placeholder' => '',
509
+ 'supplemental' => '',
510
+ 'default' => 50,
511
+ 'id' => 'ig_es_hourly_email_send_limit',
512
+ 'name' => __( 'Maximum Emails To Send In An Hour', 'email-subscribers' ),
513
+ 'desc' => __( 'Total emails your host can send in an hour.', 'email-subscribers' )
514
+ ),
515
+
516
+ 'ig_es_test_send_email' => array(
517
+ 'type' => 'html',
518
+ 'html' => '<input id="es-test-email" type="email"/><input type="submit" name="submit" id="es-send-test" class="button button-primary" value="Send Email"><span class="es_spinner_image_admin" id="spinner-image" style="display:none"><img src="' . ES_PLUGIN_URL . 'lite/public/images/spinner.gif' . '"/></span>',
519
+ 'placeholder' => '',
520
+ 'supplemental' => '',
521
+ 'default' => '',
522
+ 'id' => 'ig_es_test_send_email',
523
+ 'name' => __( 'Send Test Email', 'email-subscribers' ),
524
+ 'desc' => __( 'Enter email address to send test email.', 'email-subscribers' )
525
+ ),
526
+
527
+ 'ig_es_mailer_settings' => array(
528
+ 'type' => 'html',
529
+ // 'html' => ES_Admin_Settings::mailers_html(),
530
+ 'sub_fields' => array(
531
+ 'mailer' => array(
532
+ 'id' => 'ig_es_mailer_settings[mailer]',
533
+ 'name' => __( 'Select Mailer', 'email-subscribers' ),
534
+ 'type' => 'html',
535
+ 'html' => ES_Admin_Settings::mailers_html(),
536
+ 'desc' => '',
537
+ ),
538
+ 'ig_es_pepipost_api_key' => array(
539
+ 'type' => 'password',
540
+ 'options' => false,
541
+ 'placeholder' => '',
542
+ 'supplemental' => '',
543
+ 'default' => '',
544
+ 'id' => "ig_es_mailer_settings[pepipost][api_key]",
545
+ 'name' => __( 'Pepipost API key', 'email-subscribers' ),
546
+ 'desc' => '',
547
+ 'class' => 'pepipost'
548
+ ),
549
+ 'ig_es_pepipost_docblock' => array(
550
+ 'type' => 'html',
551
+ 'html' => ES_Admin_Settings::pepipost_doc_block(),
552
+ 'id' => 'ig_es_pepipost_docblock',
553
+ // 'class' => 'ig_es_docblock',
554
+ 'name' => ''
555
+ )
556
+
557
+ ),
558
+ 'placeholder' => '',
559
+ 'supplemental' => '',
560
+ 'default' => '',
561
+ 'id' => 'ig_es_mailer_settings',
562
+ 'name' => __( 'Select a mailer to send mail', 'email-subscribers' ),
563
+ 'desc' => ''
564
+ )
565
+ );
566
+
567
+ $email_sending_settings = apply_filters( 'ig_es_registered_email_sending_settings', $email_sending_settings );
568
+
569
+ $security_settings = array(
570
+ 'blocked_domains' => array(
571
+ 'id' => 'ig_es_blocked_domains',
572
+ 'name' => __( 'Blocked Domain(s)', 'email-subscribers' ),
573
+ 'type' => 'textarea',
574
+ 'info' => __( 'Seeing spam signups from particular domains? Enter domains names (one per line) that you want to block here.', 'email-subscribers' ),
575
+ 'default' => ''
576
+ ),
577
+
578
+ );
579
+
580
+ $security_settings = apply_filters( 'ig_es_registered_security_settings', $security_settings );
581
+
582
+ $es_settings = array(
583
+ 'general' => $general_settings,
584
+ 'signup_confirmation' => $signup_confirmation_settings,
585
+ 'email_sending' => $email_sending_settings,
586
+ 'security_settings' => $security_settings
587
+ );
588
+
589
+ return apply_filters( 'ig_es_registered_settings', $es_settings );
590
+ }
591
+
592
+ public function field_callback( $arguments, $id_key = '' ) {
593
+ $field_html = '';
594
+ if ( 'ig_es_cronurl' === $arguments['id'] ) {
595
+ $value = ES()->cron->url();
596
+ } else {
597
+ if ( ! empty( $arguments['option_value'] ) ) {
598
+ preg_match( "(\[.*$)", $arguments['id'], $m );
599
+ $n = explode( '][', $m[0] );
600
+ $n = str_replace( '[', '', $n );
601
+ $n = str_replace( ']', '', $n );
602
+ $count = count( $n );
603
+ $id = '';
604
+ foreach ( $n as $key => $val ) {
605
+ if ( $id == '' ) {
606
+ $id = ! empty( $arguments['option_value'][ $val ] ) ? $arguments['option_value'][ $val ] : '';
607
+ } else {
608
+ $id = $id[ $val ];
609
+ }
610
+ }
611
+ $value = $id;
612
+ } else {
613
+ $value = get_option( $arguments['id'] ); // Get the current value, if there is one
614
+ }
615
+ }
616
+
617
+ if ( ! $value ) { // If no value exists
618
+ $value = ! empty( $arguments['default'] ) ? $arguments['default'] : ''; // Set to our default
619
+ }
620
+
621
+ $uid = ! empty( $arguments['id'] ) ? $arguments['id'] : '';
622
+ $type = ! empty( $arguments['type'] ) ? $arguments['type'] : '';
623
+ $placeholder = ! empty( $arguments['placeholder'] ) ? $arguments['placeholder'] : '';
624
+ $readonly = ! empty( $arguments['readonly'] ) ? $arguments['readonly'] : '';
625
+ $html = ! empty( $arguments['html'] ) ? $arguments['html'] : '';
626
+ $id_key = ! empty( $id_key ) ? $id_key : $uid;
627
+ $class = ! empty( $arguments['class'] ) ? $arguments['class'] : '';
628
+ // Check which type of field we want
629
+ switch ( $arguments['type'] ) {
630
+ case 'password':
631
+ case 'text': // If it is a text field
632
+ $field_html = sprintf( '<input name="%1$s" id="%2$s" type="%3$s" placeholder="%4$s" value="%5$s" %6$s class="%7$s"/>', $uid, $id_key, $type, $placeholder, $value, $readonly, $class );
633
+ break;
634
+ case 'number': // If it is a number field
635
+ $field_html = sprintf( '<input name="%1$s" id="%1$s" type="%2$s" placeholder="%3$s" value="%4$s" %5$s min="0"/>', $uid, $type, $placeholder, $value, $readonly );
636
+ case 'password': // If it is a text field
637
+ $field_html = sprintf( '<input name="%1$s" id="%2$s" type="%3$s" placeholder="%4$s" value="%5$s" %6$s class="%7$s" />', $uid, $id_key, $type, $placeholder, $value, $readonly, $class );
638
+ break;
639
+
640
+ case 'email':
641
+ $field_html = sprintf( '<input name="%1$s" id="%2$s" type="%3$s" placeholder="%4$s" value="%5$s" class="%6$s"/>', $uid, $id_key, $type, $placeholder, $value, $class );
642
+ break;
643
+
644
+ case 'textarea':
645
+ $field_html = sprintf( '<textarea name="%1$s" id="%2$s" placeholder="%3$s" size="100" rows="12" cols="58" class="%5$s">%4$s</textarea>',
646
+ $uid, $id_key, $placeholder, $value, $class );
647
+ break;
648
+ case 'file':
649
+ $field_html = '<input type="text" id="logo_url" name="' . $uid . '" value="' . $value . '" class="' . $class . '"/> <input id="upload_logo_button" type="button" class="button" value="Upload Logo" />';
650
+ break;
651
+ case 'checkbox' :
652
+ $field_html = '<input id="' . $id_key . '" type="checkbox" name="' . $uid . '" value="yes" ' . checked( $value, 'yes', false ) . ' class="' . $class . '" />' . $placeholder . '</input>';
653
+ break;
654
+
655
+ case 'select':
656
+ if ( ! empty ( $arguments['options'] ) && is_array( $arguments['options'] ) ) {
657
+ $options_markup = "";
658
+ foreach ( $arguments['options'] as $key => $label ) {
659
+ $options_markup .= sprintf( '<option value="%s" %s>%s</option>', $key,
660
+ selected( $value, $key, false ), $label );
661
+ }
662
+ $field_html = sprintf( '<select name="%1$s" id="%2$s" class="%4$s">%3$s</select>', $uid, $id_key, $options_markup, $class );
663
+ }
664
+ break;
665
+ case 'html' :
666
+ default:
667
+ $field_html = $html;
668
+ break;
669
+ }
670
+
671
+ $field_html .= '<br />';
672
+
673
+ //If there is help text
674
+ if ( ! empty( $arguments['desc'] ) ) {
675
+ $helper = $arguments['desc'];
676
+ $field_html .= sprintf( '<span class="helper"> %s</span>', $helper ); // Show it
677
+ }
678
+
679
+ return $field_html;
680
+ }
681
+
682
+ public static function get_instance() {
683
+ if ( ! isset( self::$instance ) ) {
684
+ self::$instance = new self();
685
+ }
686
+
687
+ return self::$instance;
688
+ }
689
+
690
+ function render_settings_fields( $fields ) {
691
+
692
+ $html = "<table class='form-table'>";
693
+ $html .= "<tbody>";
694
+ $button_html = '';
695
+ foreach ( $fields as $key => $field ) {
696
+ if ( ! empty( $field['name'] ) ) {
697
+ $html .= "<tr><th scope='row'>";
698
+ $html .= $field['name'];
699
+
700
+ //If there is help text
701
+ if ( ! empty( $field['info'] ) ) {
702
+ $helper = $field['info'];
703
+ $html .= "<br />" . sprintf( '<span class="helper">%s</span>', $helper ); // Show it
704
+ }
705
+ $button_html = "<tr><td></td>";
706
+
707
+ $html .= "</th>";
708
+ }
709
+
710
+ $html .= "<td>";
711
+ if ( ! empty( $field['sub_fields'] ) ) {
712
+ $option_key = '';
713
+ foreach ( $field['sub_fields'] as $key => $sub_field ) {
714
+ if ( strpos( $sub_field['id'], '[' ) ) {
715
+ $parts = explode( '[', $sub_field['id'] );
716
+ if ( $option_key !== $parts[0] ) {
717
+ $option_value = get_option( $parts[0] );
718
+ $option_key = $parts[0];
719
+ }
720
+ $sub_field['option_value'] = is_array( $option_value ) ? $option_value : '';
721
+ }
722
+ $class = ( ! empty( $sub_field['class'] ) ) ? $sub_field['class'] : "";
723
+ $html .= ( $sub_field !== reset( $field['sub_fields'] ) ) ? '<br/>' : '';
724
+ $html .= '<div class="es_sub_headline ' . $class . '" ><strong>' . $sub_field['name'] . '</strong></div>';
725
+ $html .= $this->field_callback( $sub_field, $key );
726
+ }
727
+ } else {
728
+ $html .= $this->field_callback( $field );
729
+ }
730
+
731
+ $html .= "</td></tr>";
732
+ }
733
+
734
+ $button_html = empty( $button_html ) ? "<tr>" : $button_html;
735
+
736
+ $nonce_field = wp_nonce_field( 'update-settings', 'update-settings', true, false );
737
+
738
+ $html .= $button_html . "<td class='es-settings-submit-btn'>";
739
+ $html .= '<input type="hidden" name="submitted" value="submitted"/>';
740
+ $html .= '<input type="hidden" name="submit_action" value="ig-es-save-admin-settings"/>';
741
+ //$html .= '<input type="hidden" name="update-settings" id="update-settings" value="' . $nonce . '"/>';
742
+ $html .= $nonce_field;
743
+ $html .= '<input type="submit" name="submit" id="submit" class="button button-primary" value="' . __( 'Save Settings', 'email-subscribers' ) . '">';
744
+ $html .= "</td></tr>";
745
+ $html .= "</tbody>";
746
+ $html .= "</table>";
747
+ echo $html;
748
+
749
+ }
750
+
751
+ public static function mailers_html() {
752
+ $html = '';
753
+ $es_email_type = get_option( 'ig_es_email_type' );
754
+ $selected_mailer_settings = get_option( 'ig_es_mailer_settings' );
755
+ $selected_mailer = $selected_mailer_settings['mailer'];
756
+ $default_mailer = ( $es_email_type === 'php_html_mail' || $es_email_type === 'php_plaintext_mail' || $selected_mailer === 'phpmail' ) ? 'phpmail' : $selected_mailer;
757
+ $pepipost_doc_block = '';
758
+ $mailers = array(
759
+ 'wpmail' => array( 'name' => 'WP Mail', 'logo' => ES_PLUGIN_URL . 'lite/admin/images/wpmail.png' ),
760
+ 'phpmail' => array( 'name' => 'PHP mail', 'logo' => ES_PLUGIN_URL . 'lite/admin/images/phpmail.png' ),
761
+ 'pepipost' => array( 'name' => 'Pepipost', 'logo' => ES_PLUGIN_URL . 'lite/admin/images/pepipost.png', 'docblock' => $pepipost_doc_block ),
762
+ );
763
+ $mailers = apply_filters( 'ig_es_mailers', $mailers );
764
+ $default_mailer = ( array_key_exists( $default_mailer, $mailers ) ) ? $default_mailer : 'wpmail';
765
+ foreach ( $mailers as $key => $mailer ) {
766
+ $class = ( $key === 'pepipost' ) ? 'es_recommended' : '';
767
+ $html .= '<label><div class="es-mailer-logo ' . $class . '"><div class="es-logo-wrapper"><img src="' . $mailer['logo'] . '" alt="Default (none)"></div>';
768
+ $html .= '<input type="radio" class="es_mailer" name="ig_es_mailer_settings[mailer]" value="' . $key . '" ' . checked( $default_mailer, $key, false ) . '>' . $mailer['name'] . '</input></div></label>';
769
+ }
770
+
771
+ return $html;
772
+
773
+ }
774
+
775
+ public static function pepipost_doc_block() {
776
+ $html = '';
777
+ ob_start();
778
+ ?>
779
+ <div class="es_sub_headline ig_es_docblock ig_es_pepipost_div_wrapper pepipost">
780
+ <ul>
781
+ <li><a class="" href="https://app.pepipost.com/index.php/signup/icegram?fpr=icegram" target="_blank"><?php _e( 'Signup for Pepipost', 'email-subscribers' ) ?></a></li>
782
+ <li><?php _e( 'How to find', 'email-subscribers' ) ?> <a href="https://developers.pepipost.com/api/getstarted/overview?utm_source=icegram&utm_medium=es_inapp&utm_campaign=pepipost" target="_blank"> <?php _e( 'Pepipost API key', 'email-subscribers' ) ?></a></li>
783
+ <li><a href="https://www.icegram.com/email-subscribers-integrates-with-pepipost?utm_source=es_inapp&utm_medium=es_upsale&utm_campaign=upsale" target="_blank"><?php _e( 'Why to choose Pepipost' ) ?></a></li>
784
+ </ul>
785
+ </div>
786
+
787
+ <?php
788
+
789
+ $html = ob_get_clean();
790
+
791
+ return $html;
792
+ }
793
+
794
+ }
lite/includes/classes/class-es-campaigns-table.php ADDED
@@ -0,0 +1,432 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ if ( ! class_exists( 'WP_List_Table' ) ) {
9
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
10
+ }
11
+
12
+ class ES_Campaigns_Table extends WP_List_Table {
13
+ /**
14
+ * @since 4.2.1
15
+ * @var string
16
+ *
17
+ */
18
+ public static $option_per_page = 'es_campaigns_per_page';
19
+
20
+ /**
21
+ * ES_Campaigns_Table constructor.
22
+ *
23
+ * @since 4.0
24
+ */
25
+ public function __construct() {
26
+ parent::__construct( array(
27
+ 'singular' => __( 'Campaign', 'email-subscribers' ), //singular name of the listed records
28
+ 'plural' => __( 'Campaign', 'email-subscribers' ), //plural name of the listed records
29
+ 'ajax' => false, //does this table support ajax?
30
+ 'screen' => 'es_campaigns'
31
+ ) );
32
+ }
33
+
34
+ /**
35
+ * Add Screen Option
36
+ *
37
+ * @since 4.2.1
38
+ */
39
+ public static function screen_options() {
40
+
41
+ $option = 'per_page';
42
+ $args = array(
43
+ 'label' => __( 'Number of campaigns per page', 'email-subscribers' ),
44
+ 'default' => 20,
45
+ 'option' => self::$option_per_page
46
+ );
47
+
48
+ add_screen_option( $option, $args );
49
+
50
+ }
51
+
52
+ /**
53
+ * Render Campaigns table
54
+ *
55
+ * @since 4.0
56
+ */
57
+ public function render() {
58
+ $action = ig_es_get_request_data( 'action' );
59
+
60
+ ?>
61
+ <div class="wrap">
62
+ <h1 class="wp-heading-inline"><?php _e( 'Campaigns', 'email-subscribers' ) ?>
63
+ <a href="admin.php?page=es_notifications&action=new" class="page-title-action"><?php _e( 'Create Post Notification', 'email-subscribers' ) ?></a>
64
+ <a href="admin.php?page=es_newsletters" class="page-title-action"><?php _e( 'Send Broadcast', 'email-subscribers' ) ?></a>
65
+ <?php do_action( 'ig_es_after_campaign_type_buttons' ) ?>
66
+ <a href="edit.php?post_type=es_template" class="page-title-action es-imp-button"><?php _e( 'Manage Templates', 'email-subscribers' ) ?></a>
67
+ </h1>
68
+ <?php Email_Subscribers_Admin::es_feedback(); ?>
69
+ <div id="poststuff">
70
+ <div id="post-body" class="metabox-holder column-1">
71
+ <div id="post-body-content">
72
+ <div class="meta-box-sortables ui-sortable">
73
+ <form method="post">
74
+ <?php
75
+ $this->prepare_items();
76
+ $this->display(); ?>
77
+ </form>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ <br class="clear">
82
+ </div>
83
+ </div>
84
+ <?php
85
+ }
86
+
87
+ public function custom_admin_notice() {
88
+ $es_note_cat = ig_es_get_request_data( 'es_note_cat' );
89
+
90
+ if ( $es_note_cat ) {
91
+ echo '<div class="updated"><p>Notification Added Successfully!</p></div>';
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Retrieve lists data from the database
97
+ *
98
+ * @param int $per_page
99
+ * @param int $page_number
100
+ *
101
+ * @return mixed
102
+ */
103
+ public static function get_lists( $per_page = 5, $page_number = 1, $do_count_only = false ) {
104
+
105
+ global $wpdb;
106
+
107
+ $order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
108
+ $order = ig_es_get_request_data( 'order' );
109
+ $search = ig_es_get_request_data( 's' );
110
+
111
+ if ( $do_count_only ) {
112
+ $sql = "SELECT count(*) as total FROM " . IG_CAMPAIGNS_TABLE;
113
+ } else {
114
+ $sql = "SELECT * FROM " . IG_CAMPAIGNS_TABLE;
115
+ }
116
+
117
+ $args = $query = array();
118
+ $add_where_clause = true;
119
+
120
+ $query[] = "( deleted_at IS NULL OR deleted_at = '0000-00-00 00:00:00' )";
121
+
122
+
123
+ if ( ! empty( $search ) ) {
124
+ $query[] = " name LIKE %s ";
125
+ $args[] = "%" . $wpdb->esc_like( $search ) . "%";
126
+ }
127
+
128
+ $query = apply_filters( 'ig_es_campaign_list_where_caluse', $query );
129
+
130
+ if ( $add_where_clause ) {
131
+ $sql .= " WHERE ";
132
+
133
+ if ( count( $query ) > 0 ) {
134
+ $sql .= implode( " AND ", $query );
135
+
136
+ if ( count( $args ) > 0 ) {
137
+ $sql = $wpdb->prepare( $sql, $args );
138
+ }
139
+ }
140
+ }
141
+
142
+ if ( ! $do_count_only ) {
143
+
144
+ $order = ! empty( $order ) ? strtolower( $order ) : 'desc';
145
+ $expected_order_values = array( 'asc', 'desc' );
146
+ if ( ! in_array( $order, $expected_order_values ) ) {
147
+ $order = 'desc';
148
+ }
149
+
150
+ $default_order_by = esc_sql( 'created_at' );
151
+
152
+ $expected_order_by_values = array( 'base_template_id', 'type' );
153
+ if ( ! in_array( $order_by, $expected_order_by_values ) ) {
154
+ $order_by_clause = " ORDER BY {$default_order_by} DESC";
155
+ } else {
156
+ $order_by = esc_sql( $order_by );
157
+ $order_by_clause = " ORDER BY {$order_by} {$order}, {$default_order_by} DESC";
158
+ }
159
+
160
+ $sql .= $order_by_clause;
161
+ $sql .= " LIMIT $per_page";
162
+ $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
163
+
164
+ $result = $wpdb->get_results( $sql, 'ARRAY_A' );
165
+ } else {
166
+ $result = $wpdb->get_var( $sql );
167
+ }
168
+
169
+ return $result;
170
+ }
171
+
172
+ /**
173
+ * Text Display when no items available
174
+ *
175
+ * @since 4.0
176
+ */
177
+ public function no_items() {
178
+ _e( 'No Campaigns Found.', 'email-subscribers' );
179
+ }
180
+
181
+ /**
182
+ * Render a column when no column specific method exist.
183
+ *
184
+ * @param array $item
185
+ * @param string $column_name
186
+ *
187
+ * @return mixed
188
+ */
189
+ public function column_default( $item, $column_name ) {
190
+ switch ( $column_name ) {
191
+
192
+ case 'list_ids':
193
+ if ( ! empty( $item[ $column_name ] ) ) {
194
+ return ES()->lists_db->get_list_id_name_map( $item[ $column_name ] );
195
+ } else {
196
+ return '-';
197
+ }
198
+ break;
199
+ case 'status':
200
+ $status = ( $item[ $column_name ] == 1 ) ? __( 'Active', 'email-subscribers' ) : __( 'Inactive', 'email-subscribers' );
201
+
202
+ return $status;
203
+
204
+ break;
205
+ case 'type':
206
+ $type = ( $item[ $column_name ] === 'newsletter' ) ? __( 'Broadcast', 'email-subscribers' ) : $item[ $column_name ];
207
+ $type = ucwords( str_replace( '_', ' ', $type ) );
208
+
209
+ return $type;
210
+ break;
211
+ case 'categories':
212
+ if ( ! empty( $item[ $column_name ] ) ) {
213
+ $categories = ES_Common::convert_categories_string_to_array( $item[ $column_name ], false );
214
+ $categories = strpos( $item[ $column_name ], '{a}All{a}' ) ? __( 'All', 'email-subscribers' ) : trim( trim( implode( ', ', $categories ) ), ',' );
215
+
216
+ return $categories;
217
+ } else {
218
+ return '-';
219
+ }
220
+ break;
221
+ default:
222
+ return $item[ $column_name ];
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Render the bulk edit checkbox
228
+ *
229
+ * @param array $item
230
+ *
231
+ * @return string
232
+ */
233
+ function column_cb( $item ) {
234
+ return sprintf(
235
+ '<input type="checkbox" name="campaigns[]" value="%s" />', $item['id']
236
+ );
237
+ }
238
+
239
+ /**
240
+ * Method for name column
241
+ *
242
+ * @param array $item an array of DB data
243
+ *
244
+ * @return string
245
+ */
246
+ function column_base_template_id( $item ) {
247
+
248
+ $type = $item['type'];
249
+
250
+
251
+ $nonce = wp_create_nonce( 'es_post_notification' );
252
+
253
+ if ( $type !== 'newsletter' ) {
254
+
255
+ $template = get_post( $item['base_template_id'] );
256
+
257
+ if ( $template instanceof WP_Post ) {
258
+ $title = '<strong>' . $template->post_title . '</strong>';
259
+ } else {
260
+ $title = ! empty( $item['name'] ) ? $item['name'] : '';
261
+ }
262
+
263
+ $slug = ( in_array( $item['type'], array( 'post_notification', 'post_digest' ) ) ) ? esc_attr( 'es_notifications' ) : 'es_' . $item['type'];
264
+
265
+ $actions ['edit'] = sprintf( __( '<a href="?page=%s&action=%s&list=%s&_wpnonce=%s">Edit</a>', 'email-subscribers' ), $slug, 'edit', absint( $item['id'] ), $nonce );
266
+ $actions['delete'] = sprintf( __( '<a href="?page=%s&action=%s&list=%s&_wpnonce=%s" onclick="return checkDelete()">Delete</a>', 'email-subscribers' ), esc_attr( 'es_campaigns' ), 'delete', absint( $item['id'] ), $nonce );
267
+
268
+ $title .= $this->row_actions( $actions );
269
+ } else {
270
+ $title = $item['name'];
271
+ }
272
+
273
+ return $title;
274
+ }
275
+
276
+
277
+ /**
278
+ * Associative array of columns
279
+ *
280
+ * @return array
281
+ */
282
+ function get_columns() {
283
+ $columns = array(
284
+ 'cb' => '<input type="checkbox" />',
285
+ 'base_template_id' => __( 'Name', 'email-subscribers' ),
286
+ 'type' => __( 'Type', 'email-subscribers' ),
287
+ 'list_ids' => __( 'List', 'email-subscribers' ),
288
+ 'categories' => __( 'Categories', 'email-subscribers' ),
289
+ 'status' => __( 'Status', 'email-subscribers' )
290
+ );
291
+
292
+ return $columns;
293
+ }
294
+
295
+
296
+ /**
297
+ * Columns to make sortable.
298
+ *
299
+ * @return array
300
+ */
301
+ public function get_sortable_columns() {
302
+ $sortable_columns = array(
303
+ //'base_template_id' => array( 'base_template_id', true ),
304
+ //'list_ids' => array( 'list_ids', true ),
305
+ //'status' => array( 'status', true )
306
+ 'type' => array( 'type', true )
307
+ );
308
+
309
+ return $sortable_columns;
310
+ }
311
+
312
+ /**
313
+ * Returns an associative array containing the bulk action
314
+ *
315
+ * @return array
316
+ */
317
+ public function get_bulk_actions() {
318
+ $actions = array(
319
+ 'bulk_delete' => 'Delete'
320
+ );
321
+
322
+ return $actions;
323
+ }
324
+
325
+ public function search_box( $text, $input_id ) { ?>
326
+ <p class="search-box">
327
+ <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
328
+ <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>"/>
329
+ <?php submit_button( __( 'Search Campaigns', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
330
+ </p>
331
+ <?php }
332
+
333
+ /**
334
+ * Handles data query and filter, sorting, and pagination.
335
+ */
336
+ public function prepare_items() {
337
+
338
+ $this->_column_headers = $this->get_column_info();
339
+
340
+ /** Process bulk action */
341
+ $this->process_bulk_action();
342
+
343
+ // Note: Disable Search box for now.
344
+ $search = ig_es_get_request_data( 's' );
345
+ $this->search_box( $search, 'notification-search-input' );
346
+
347
+ $per_page = $this->get_items_per_page( self::$option_per_page, 25 );
348
+
349
+ $current_page = $this->get_pagenum();
350
+ $total_items = $this->get_lists( 0, 0, true );
351
+
352
+ $this->set_pagination_args( array(
353
+ 'total_items' => $total_items, //We have to calculate the total number of items
354
+ 'per_page' => $per_page //We have to determine how many items to show on a page
355
+ ) );
356
+
357
+ $this->items = $this->get_lists( $per_page, $current_page );
358
+ }
359
+
360
+ public function process_bulk_action() {
361
+
362
+ if ( 'delete' === $this->current_action() ) {
363
+
364
+ // In our file that handles the request, verify the nonce.
365
+ $nonce = ig_es_get_request_data( '_wpnonce' );
366
+
367
+ if ( ! wp_verify_nonce( $nonce, 'es_post_notification' ) ) {
368
+ $message = __( 'You are not allowed to delete campaign.', 'email-subscribers' );
369
+ $status = 'error';
370
+ } else {
371
+ $list = ig_es_get_request_data( 'list' );
372
+ $this->delete_list( array( $list ) );
373
+ $message = __( 'Campaign has been deleted successfully!', 'email-subscribers' );
374
+ $status = 'success';
375
+ }
376
+
377
+ ES_Common::show_message( $message, $status );
378
+ }
379
+
380
+ $action = ig_es_get_request_data( 'action' );
381
+ $action2 = ig_es_get_request_data( 'action2' );
382
+ // If the delete bulk action is triggered
383
+ if ( ( 'bulk_delete' === $action ) || ( 'bulk_delete' === $action2 ) ) {
384
+
385
+ $ids = ig_es_get_request_data( 'campaigns' );
386
+
387
+ if ( is_array( $ids ) && count( $ids ) > 0 ) {
388
+
389
+ $deleted = $this->delete_list( $ids );
390
+
391
+ if ( $deleted ) {
392
+ $message = __( 'Campaign(s) have been deleted successfully!', 'email-subscribers' );
393
+ ES_Common::show_message( $message );
394
+ }
395
+ } else {
396
+
397
+ $message = __( 'Please check campaign(s) to delete.', 'email-subscribers' );
398
+ ES_Common::show_message( $message, 'error' );
399
+ }
400
+
401
+
402
+ }
403
+ }
404
+
405
+ /**
406
+ * Delete a list record.
407
+ *
408
+ * @param int $id list ID
409
+ */
410
+ public function delete_list( $ids ) {
411
+ global $wpdb;
412
+
413
+ if ( is_array( $ids ) && count( $ids ) > 0 ) {
414
+
415
+ $campaigns_table = IG_CAMPAIGNS_TABLE;
416
+
417
+ $ids = implode( ',', array_map( 'absint', $ids ) );
418
+
419
+ $current_date = gmdate( 'Y-m-d G:i:s' );
420
+ $query = "UPDATE {$campaigns_table} SET deleted_at = %s WHERE id IN ($ids)";
421
+ $query = $wpdb->prepare( $query, array( $current_date ) );
422
+ $result = $wpdb->query( $query );
423
+
424
+ if ( $result ) {
425
+ return true;
426
+ }
427
+ }
428
+
429
+ return false;
430
+ }
431
+
432
+ }
lite/includes/classes/class-es-contacts-table.php ADDED
@@ -0,0 +1,1110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ if ( ! class_exists( 'WP_List_Table' ) ) {
9
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
10
+ }
11
+
12
+ class ES_Contacts_Table extends WP_List_Table {
13
+ /**
14
+ * @since 4.0.0
15
+ * @var array
16
+ *
17
+ */
18
+ public $contact_lists_statuses = array();
19
+
20
+ /**
21
+ * @since 4.2.1
22
+ *
23
+ * @var string
24
+ */
25
+ public static $option_per_page = 'es_contacts_per_page';
26
+
27
+ /**
28
+ * @since 4.0.0
29
+ * @var array
30
+ *
31
+ */
32
+ public $list_ids = array();
33
+
34
+ /**
35
+ * @since 4.0.0
36
+ * @var array
37
+ *
38
+ */
39
+ public $lists_id_name_map = array();
40
+
41
+ public function __construct() {
42
+
43
+ //set_error_handler(array( 'Email_General' , 'es_handle_error'));
44
+ parent::__construct( array(
45
+ 'singular' => __( 'Contact', 'email-subscribers' ), //singular name of the listed records
46
+ 'plural' => __( 'Contacts', 'email-subscribers' ), //plural name of the listed records
47
+ 'ajax' => false,//does this table support ajax?
48
+ 'screen' => 'es_subscribers'
49
+ ) );
50
+
51
+ add_filter( 'ig_es_audience_tab_main_navigation', array( $this, 'get_audience_main_tabs' ), 10, 2 );
52
+
53
+ // @since 4.3.1
54
+ add_action( 'ig_es_list_deleted', array( $this, 'delete_contacts_from_list' ), 10, 1 );
55
+ add_action( 'ig_es_form_deleted', array( $this, 'set_default_form_id' ), 10, 1 );
56
+ }
57
+
58
+ /**
59
+ * Add Screen Option
60
+ *
61
+ * @since 4.2.1
62
+ */
63
+ public static function screen_options() {
64
+
65
+ // Don't show screen option on Import/ Export subscribers page.
66
+ $action = ig_es_get_request_data( 'action' );
67
+
68
+ if ( '' === $action ) {
69
+
70
+ $option = 'per_page';
71
+ $args = array(
72
+ 'label' => __( 'Number of contacts per page', 'email-subscribers' ),
73
+ 'default' => 100,
74
+ 'option' => self::$option_per_page
75
+ );
76
+
77
+ add_screen_option( $option, $args );
78
+ }
79
+
80
+ }
81
+
82
+
83
+ public function get_audience_main_tabs( $active_tab, $audience_main_tabs = array() ) {
84
+
85
+ $audience_tab_main_navigation = array(
86
+ 'new_contact' => array(
87
+ 'label' => __( 'Add New Contact', 'email-subscribers' ),
88
+ 'indicator_option' => '',
89
+ 'indicator_label' => '',
90
+ 'indicator_type' => '',
91
+ 'action' => 'new',
92
+ 'url' => add_query_arg( 'action', 'new', 'admin.php?page=es_subscribers' )
93
+ ),
94
+
95
+ 'export' => array(
96
+ 'label' => __( 'Export Contacts', 'email-subscribers' ),
97
+ 'indicator_option' => '',
98
+ 'indicator_label' => '',
99
+ 'indicator_type' => '',
100
+ 'action' => 'export',
101
+ 'url' => add_query_arg( 'action', 'export', 'admin.php?page=es_subscribers' )
102
+ ),
103
+
104
+ 'import' => array(
105
+ 'label' => __( 'Import Contacts', 'email-subscribers' ),
106
+ 'indicator_option' => '',
107
+ 'indicator_label' => '',
108
+ 'indicator_type' => '',
109
+ 'action' => 'import',
110
+ 'url' => add_query_arg( 'action', 'import', 'admin.php?page=es_subscribers' )
111
+ ),
112
+
113
+ 'sync' => array(
114
+ 'label' => __( 'Sync', 'email-subscribers' ),
115
+ 'indicator_option' => 'ig_es_show_sync_tab',
116
+ 'indicator_label' => __( 'New', 'email-subscribers' ),
117
+ 'indicator_type' => 'new',
118
+ 'action' => 'sync',
119
+ 'url' => add_query_arg( 'action', 'sync', 'admin.php?page=es_subscribers' )
120
+ ),
121
+
122
+ 'manage_lists' => array(
123
+ 'label' => __( 'Manage Lists', 'email-subscribers' ),
124
+ 'indicator_option' => '',
125
+ 'indicator_label' => '',
126
+ 'indicator_type' => '',
127
+ 'action' => 'manage-lists',
128
+ 'is_imp' => true,
129
+ 'url' => add_query_arg( 'action', 'manage-lists', 'admin.php?page=es_lists' )
130
+ )
131
+ );
132
+
133
+ $audience_main_tabs = $audience_main_tabs + $audience_tab_main_navigation;
134
+
135
+ if ( ! empty( $active_tab ) && isset( $audience_main_tabs[ $active_tab ] ) ) {
136
+ unset( $audience_main_tabs[ $active_tab ] );
137
+ }
138
+
139
+ return $audience_main_tabs;
140
+ }
141
+
142
+ /**
143
+ * Render Audience View
144
+ *
145
+ * @since 4.2.1
146
+ */
147
+ public function render() {
148
+
149
+ ?>
150
+ <div class="wrap">
151
+
152
+ <?php
153
+
154
+ $action = ig_es_get_request_data( 'action' );
155
+ if ( 'import' === $action ) {
156
+ $this->load_import();
157
+ } elseif ( 'export' === $action ) {
158
+ $this->load_export();
159
+ } elseif ( 'new' === $action || 'edit' === $action ) {
160
+ $contact_id = absint( ig_es_get_request_data( 'subscriber' ) );
161
+ $this->save_contact( $contact_id );
162
+ } elseif ( 'sync' === $action ) {
163
+ update_option( 'ig_es_show_sync_tab', 'no' ); // yes/no
164
+ $this->load_sync();
165
+ } else {
166
+
167
+ $audience_tab_main_navigation = array();
168
+ $active_tab = '';
169
+ $audience_tab_main_navigation = apply_filters( 'ig_es_audience_tab_main_navigation', $active_tab, $audience_tab_main_navigation );
170
+
171
+ ?>
172
+
173
+ <h1 class="wp-heading-inline">
174
+ <?php
175
+ _e( 'Audience > Contacts', 'email-subscribers' );
176
+ ES_Common::prepare_main_header_navigation( $audience_tab_main_navigation );
177
+ ?>
178
+ </h1>
179
+ <div class="es-contact-reports">
180
+ <?php $this->get_contacts_reports()?>
181
+ </div>
182
+
183
+ <?php Email_Subscribers_Admin::es_feedback(); ?>
184
+ <div id="poststuff" class="es-audience-view">
185
+ <div id="post-body" class="metabox-holder column-1">
186
+ <div id="post-body-content">
187
+ <div class="meta-box-sortables ui-sortable">
188
+ <form method="post">
189
+ <?php
190
+ $this->prepare_items();
191
+ $this->display();
192
+ ?>
193
+ </form>
194
+ </div>
195
+ </div>
196
+ </div>
197
+ <br class="clear">
198
+ </div>
199
+ </div>
200
+ <?php }
201
+ }
202
+
203
+ public function load_export() {
204
+ $export = new Export_Subscribers();
205
+ $export->export_subscribers_page();
206
+ }
207
+
208
+ public function load_import() {
209
+ $import = new ES_Import_Subscribers();
210
+ $import->import_subscribers_page();
211
+ }
212
+
213
+ public function load_sync() {
214
+ $sync = ES_Handle_Sync_Wp_User::get_instance();
215
+ $sync->prepare_sync_user();
216
+ }
217
+
218
+ public function get_contacts_reports(){
219
+ $es_total_contact = ES_Reports_Data::get_total_contacts();
220
+ $es_total_subscribed_contacts = ES_Reports_Data::get_total_subscribed_contacts( 60 );
221
+ $es_total_unsubscribed_contacts = ES_Reports_Data::get_total_unsubscribed_contacts( 60 );
222
+ $es_total_contacts_opened_emails = ES_Reports_Data::get_total_contacts_opened_emails( 60 );
223
+ ?>
224
+ <div class="es_total_contact">
225
+ <h2 class="es_contact_kpi_text"><?php _e('Contacts', 'email-subscribers'); ?></h2>
226
+ <span class="es_contact_kpi_no"><?php echo $es_total_contact; ?></span></br>
227
+ </div>
228
+ <div class="es_last_60_days">
229
+ <h2><?php _e('Last 60 Days', 'email-subscribers'); ?></h2>
230
+ <div class="es_contact_kpi">
231
+ <span class="es_contact_kpi_no" style="color: #009e00"><?php echo $es_total_subscribed_contacts; ?></span></br>
232
+ <span class="es_contact_kpi_text"><?php _e('Subscribed', 'email-subscribers'); ?></span>
233
+ </div>
234
+ <div class="es_contact_kpi">
235
+ <span class="es_contact_kpi_no" style="color: #d40303"><?php echo $es_total_unsubscribed_contacts; ?></span></br>
236
+ <span class="es_contact_kpi_text"><?php _e('Unsubscribed', 'email-subscribers'); ?></span>
237
+ </div>
238
+ <div class="es_contact_kpi">
239
+ <span class="es_contact_kpi_no" style="color: #006cc1"><?php echo $es_total_contacts_opened_emails; ?></span></br>
240
+ <span class="es_contact_kpi_text"><?php _e('Opened', 'email-subscribers'); ?></span>
241
+ </div>
242
+ <?php do_action('ig_es_after_contacts_kpis'); ?>
243
+ </div>
244
+ <?php
245
+ }
246
+
247
+ public function save_contact( $id = 0 ) {
248
+ global $wpdb;
249
+
250
+ $first_name = $action = $last_name = $email = $guid = $created = '';
251
+ $list_ids = array();
252
+ $is_new = true;
253
+
254
+ if ( $id === 0 ) {
255
+ $title = __( 'Add New Contact', 'email-subscribers' );
256
+ $title_action = '<a href="admin.php?page=es_lists&action=manage-lists" class="page-title-action es-imp-button">' . __( 'Manage Lists', 'email-subscribers' ) . '</a>';
257
+
258
+ } else {
259
+ $is_new = false;
260
+ $title = __( 'Edit Contact', 'email-subscribers' );
261
+ $title_action = '<a href="admin.php?page=es_subscribers&action=new" class="page-title-action">' . __( 'Add New', 'email-subscribers' ) . '</a>';
262
+
263
+ $contacts_table = IG_CONTACTS_TABLE;
264
+ $query = "SELECT * FROM {$contacts_table} WHERE id = %d";
265
+ $contact = $wpdb->get_results( $wpdb->prepare( $query, $id ), ARRAY_A );
266
+
267
+ if ( ! empty( $contact[0] ) ) {
268
+ $contact = $contact[0];
269
+
270
+ $first_name = ! empty( $contact['first_name'] ) ? $contact['first_name'] : '';
271
+ $last_name = ! empty( $contact['last_name'] ) ? $contact['last_name'] : '';
272
+ $email = ! empty( $contact['email'] ) ? $contact['email'] : '';
273
+ $list_ids = ES_DB_Lists_Contacts::get_list_ids_by_contact( $id );
274
+ $guid = $contact['hash'];
275
+ $nonce = esc_attr( ig_es_get_request_data( '_wpnonce' ) );
276
+ }
277
+ }
278
+
279
+ $submitted = ig_es_get_request_data( 'submitted' );
280
+ if ( 'submitted' === $submitted ) {
281
+
282
+ $contact_data = ig_es_get_post_data( 'contact_data', array() );
283
+ $is_error = false;
284
+ if ( ! empty( $contact_data ) ) {
285
+
286
+ $email = ! empty( $contact_data['email'] ) ? sanitize_email( $contact_data['email'] ) : '';
287
+
288
+ if ( $email ) {
289
+
290
+ $list_ids = ! empty( $contact_data['lists'] ) ? $contact_data['lists'] : array();
291
+
292
+ if ( count( $list_ids ) > 0 ) {
293
+ $first_name = ! empty( $contact_data['first_name'] ) ? sanitize_text_field( $contact_data['first_name'] ) : '';
294
+ $last_name = ! empty( $contact_data['last_name'] ) ? sanitize_text_field( $contact_data['last_name'] ) : '';
295
+
296
+ if ( ! empty( $first_name ) ) {
297
+
298
+ $contact = array(
299
+ 'first_name' => $first_name,
300
+ 'last_name' => $last_name,
301
+ 'email' => $email,
302
+ );
303
+
304
+ // Add contact
305
+ if ( $id ) {
306
+ ES()->contacts_db->update_contact( $id, $contact );
307
+ } else {
308
+ $id = ES()->contacts_db->get_contact_id_by_email( $email );
309
+ if ( ! $id ) {
310
+ $contact['source'] = 'admin';
311
+ $contact['status'] = 'verified';
312
+ $contact['hash'] = ES_Common::generate_guid();
313
+ $contact['created_at'] = ig_get_current_date_time();
314
+
315
+ $id = ES()->contacts_db->insert( $contact );
316
+
317
+ } else {
318
+ $message = __( 'Contact already exist.', 'email-subscribers' );
319
+ ES_Common::show_message( $message, 'error' );
320
+ $is_error = true;
321
+ }
322
+
323
+ }
324
+
325
+ if ( ! $is_error ) {
326
+
327
+ $list_ids = ! empty( $list_ids ) ? $list_ids : array( 1 );
328
+
329
+ ES_DB_Lists_Contacts::update_list_contacts( $id, $list_ids );
330
+
331
+ if ( $id ) {
332
+
333
+ if ( $is_new ) {
334
+
335
+ if ( ! empty( $contact_data['send_welcome_email'] ) ) {
336
+
337
+ // Get comma(,) separated list name based on ids
338
+ $list_name = ES_Common::prepare_list_name_by_ids( $list_ids );
339
+ $name = ES_Common::prepare_name_from_first_name_last_name( $contact['first_name'], $contact['last_name'] );
340
+
341
+ $template_data = array(
342
+ 'email' => $contact['email'],
343
+ 'contact_id' => $id,
344
+ 'name' => $name,
345
+ 'first_name' => $contact['first_name'],
346
+ 'last_name' => $contact['last_name'],
347
+ 'guid' => $contact['hash'],
348
+ 'list_name' => $list_name
349
+ );
350
+
351
+ // Send Welcome Email
352
+ ES()->mailer->send_welcome_email( $contact['email'], $template_data );
353
+ }
354
+
355
+ $message = __( 'Contact has been added successfully!', 'email-subscribers' );
356
+ } else {
357
+ $message = __( 'Contact has been updated successfully!', 'email-subscribers' );
358
+ }
359
+
360
+ ES_Common::show_message( $message, 'success' );
361
+ }
362
+ }
363
+ } else {
364
+ $message = __( 'Please Enter First Name', 'email-subscribers' );
365
+ ES_Common::show_message( $message, 'error' );
366
+ }
367
+
368
+ } else {
369
+ $message = __( 'Please Select List', 'email-subscribers' );
370
+ ES_Common::show_message( $message, 'error' );
371
+ }
372
+
373
+ } else {
374
+ $message = __( 'Please Enter Valid Email Address', 'email-subscribers' );
375
+ ES_Common::show_message( $message, 'error' );
376
+ }
377
+
378
+ }
379
+ }
380
+
381
+ $data = array(
382
+ 'id' => $id,
383
+ 'first_name' => $first_name,
384
+ 'last_name' => $last_name,
385
+ 'email' => $email,
386
+ 'selected_list_ids' => $list_ids,
387
+ 'guid' => $guid
388
+ );
389
+
390
+ ?>
391
+
392
+ <div class="wrap">
393
+ <h1 class="wp-heading-inline"><?php echo $title; ?><?php echo $title_action; ?></h1><?php Email_Subscribers_Admin::es_feedback(); ?>
394
+ <hr class="wp-header-end">
395
+ <div id="poststuff">
396
+ <div id="post-body" class="metabox-holder column-1">
397
+ <div id="post-body-content">
398
+ <div class="meta-box-sortables ui-sortable es-contact-form">
399
+ <?php echo $this->prepare_contact_form( $data, $is_new ); ?>
400
+ </div>
401
+ </div>
402
+ </div>
403
+ </div>
404
+ </div>
405
+
406
+ <?php
407
+
408
+ }
409
+
410
+ /**
411
+ * Retrieve subscribers data from the database
412
+ *
413
+ * @param int $per_page
414
+ * @param int $page_number
415
+ *
416
+ * @return mixed
417
+ */
418
+ public function get_subscribers( $per_page = 5, $page_number = 1, $do_count_only = false ) {
419
+ global $wpdb;
420
+
421
+ $order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
422
+ $order = ig_es_get_request_data( 'order' );
423
+ $search = ig_es_get_request_data( 's' );
424
+ $filter_by_list_id = ig_es_get_request_data( 'filter_by_list_id' );
425
+ $filter_by_status = ig_es_get_request_data( 'filter_by_status' );
426
+
427
+ $contacts_table = IG_CONTACTS_TABLE;
428
+ $lists_contacts_table = IG_LISTS_CONTACTS_TABLE;
429
+
430
+ $add_where_clause = false;
431
+
432
+ $args = array();
433
+ $query = array();
434
+
435
+ if ( $do_count_only ) {
436
+ $sql = "SELECT count(*) FROM {$contacts_table}";
437
+ } else {
438
+ $sql = "SELECT * FROM {$contacts_table}";
439
+ }
440
+
441
+ // Prepare filter by list query
442
+ if ( ! empty( $filter_by_list_id ) || ! empty( $filter_by_status ) ) {
443
+ $add_where_clause = true;
444
+
445
+ $filter_sql = "SELECT contact_id FROM {$lists_contacts_table}";
446
+
447
+ $list_filter_sql = '';
448
+ $where_clause_added = false;
449
+
450
+ if ( ! empty( $filter_by_list_id ) ) {
451
+ $list_filter_sql = $wpdb->prepare( " WHERE list_id = %d", $filter_by_list_id );
452
+ $where_clause_added = true;
453
+ }
454
+
455
+ if ( ! empty( $filter_by_status ) ) {
456
+ if ( $where_clause_added ) {
457
+ $list_filter_sql .= $wpdb->prepare( " AND status = %s", $filter_by_status );
458
+ } else {
459
+ $list_filter_sql .= $wpdb->prepare( " WHERE status = %s", $filter_by_status );
460
+ }
461
+
462
+ }
463
+
464
+ $filter_sql .= $list_filter_sql;
465
+ $query[] = "id IN ( $filter_sql )";
466
+ }
467
+
468
+ // Prepare search query
469
+ if ( ! empty( $search ) ) {
470
+ $query[] = " ( first_name LIKE %s OR last_name LIKE %s OR email LIKE %s ) ";
471
+ $args[] = "%" . $wpdb->esc_like( $search ) . "%";
472
+ $args[] = "%" . $wpdb->esc_like( $search ) . "%";
473
+ $args[] = "%" . $wpdb->esc_like( $search ) . "%";
474
+ }
475
+
476
+ if ( $add_where_clause || count( $query ) > 0 ) {
477
+ $sql .= " WHERE ";
478
+
479
+ if ( count( $query ) > 0 ) {
480
+ $sql .= implode( " AND ", $query );
481
+ if ( ! empty( $args ) ) {
482
+ $sql = $wpdb->prepare( $sql, $args );
483
+ }
484
+ }
485
+ }
486
+
487
+
488
+ if ( ! $do_count_only ) {
489
+
490
+ // Prepare Order by clause
491
+ $order = ! empty( $order ) ? strtolower( $order ) : 'desc';
492
+ $expected_order_values = array( 'asc', 'desc' );
493
+ if ( ! in_array( $order, $expected_order_values ) ) {
494
+ $order = 'desc';
495
+ }
496
+
497
+ $offset = ( $page_number - 1 ) * $per_page;
498
+
499
+ $expected_order_by_values = array( 'name', 'email', 'created_at', 'first_name' );
500
+ if ( ! in_array( $order_by, $expected_order_by_values ) ) {
501
+ $order_by = 'created_at';
502
+ }
503
+
504
+ $order_by = esc_sql( $order_by );
505
+
506
+ $order_by_clause = " ORDER BY {$order_by} {$order}";
507
+
508
+ $sql .= $order_by_clause;
509
+ $sql .= " LIMIT {$offset}, {$per_page}";
510
+
511
+ $result = $wpdb->get_results( $sql, 'ARRAY_A' );
512
+ } else {
513
+ $result = $wpdb->get_var( $sql );
514
+ }
515
+
516
+ return $result;
517
+ }
518
+
519
+ public function edit_list( $id ) {
520
+ global $wpdb;
521
+
522
+ $notificationid = $wpdb->get_results( "SELECT * FROM " . IG_CONTACTS_TABLE . " WHERE id = $id" );
523
+
524
+ $title = $notificationid[0]->first_name . ' ' . $notificationid[0]->last_name;
525
+ $email = $notificationid[0]->email;
526
+ $contact_lists = ES_DB_Lists_Contacts::get_list_ids_by_contact( $notificationid[0]->id );
527
+
528
+ $status = ig_es_get_request_data( 'status' );
529
+ if ( 'updated' === $status ) {
530
+ $email_address = sanitize_email( ig_es_get_request_data( 'email' ) );
531
+
532
+ if ( ! empty( $email_address ) ) {
533
+ $this->update_list( $id );
534
+ $title = ig_es_get_request_data( 'subscriber_name' );
535
+ $contact_lists = ig_es_get_request_data( 'lists' );
536
+ $email = $email_address;
537
+ }
538
+ }
539
+
540
+ $id = $notificationid[0]->id;
541
+ $guid = $notificationid[0]->hash;
542
+ $created = $notificationid[0]->created_at;
543
+ $nonce = esc_attr( ig_es_get_request_data( '_wpnonce' ) );
544
+
545
+ $data = array(
546
+ 'id' => $id,
547
+ 'action' => "admin.php?page=es_subscribers&action=edit&subscriber={$id}&_wpnonce={$nonce}&status=updated",
548
+ 'name' => $title,
549
+ 'email' => $email,
550
+ 'created' => $created,
551
+ 'guid' => $guid,
552
+ 'selected_list_ids' => $contact_lists
553
+ );
554
+
555
+ $contact_name = ig_es_get_request_data( 'subscriber_name' );
556
+ if ( $contact_name ) {
557
+ $message = __( 'Contact updated successfully!', 'email-subscribers' );
558
+ ES_Common::show_message( $message, 'success' );
559
+ }
560
+
561
+ $editform = '<div class="wrap">
562
+ <h1 class="wp-heading-inline">' . __( 'Edit Contact', 'email-subscribers' ) . '<a href="admin.php?page=es_subscribers&action=new" class="page-title-action">Add New</a></h1>' . Email_Subscribers_Admin::es_feedback() . '
563
+ <hr class="wp-header-end">
564
+ <div id="poststuff">
565
+ <div id="post-body" class="metabox-holder column-1">
566
+ <div id="post-body-content">
567
+ <div class="meta-box-sortables ui-sortable es-contact-form">'
568
+ . $this->prepare_contact_form( $data, false ) .
569
+ '</div>
570
+ </div>
571
+ </div>
572
+ </div>
573
+ </div>';
574
+
575
+ return $editform;
576
+ }
577
+
578
+ public function prepare_contact_form( $data = array(), $is_new = false ) {
579
+
580
+ $id = ! empty( $data['id'] ) ? $data['id'] : '';
581
+ $created = ! empty( $data['created'] ) ? $data['created'] : '';
582
+ $guid = ! empty( $data['guid'] ) ? $data['guid'] : '';
583
+ $action = ! empty( $data['action'] ) ? $data['action'] : '#';
584
+ $first_name = ! empty( $data['first_name'] ) ? $data['first_name'] : '';
585
+ $last_name = ! empty( $data['last_name'] ) ? $data['last_name'] : '';
586
+ $email = ! empty( $data['email'] ) ? $data['email'] : '';
587
+ $selected_list_ids = ! empty( $data['selected_list_ids'] ) ? $data['selected_list_ids'] : array();
588
+ $send_welcome_email = ! empty( $data['send_welcome_email'] ) ? true : false;
589
+
590
+ $lists_id_name_map = ES()->lists_db->get_list_id_name_map();
591
+
592
+ if ( count( $lists_id_name_map ) ) {
593
+ $list_html = ES_Shortcode::prepare_lists_checkboxes( $lists_id_name_map, array_keys( $lists_id_name_map ), 4, $selected_list_ids, $id, 'contact_data[lists][]' );
594
+ } else {
595
+ $list_html = "<tr><td>" . __( 'No list found', 'email-subscribers' ) . "</td></tr>";
596
+ }
597
+
598
+ ?>
599
+ <form method="post" action="<?php echo $action; ?>">
600
+ <table class="ig-es-form-table form-table">
601
+ <tbody>
602
+ <tr class="form-field">
603
+ <td><label><b><?php _e( 'First Name', 'email-subscribers' ); ?></b></label></td>
604
+ <td><input type="text" class="ig-es-contact-first-name" id="ig-es-contact-first-name" name="contact_data[first_name]" value="<?php echo $first_name; ?>"/></td>
605
+ </tr>
606
+
607
+ <tr class="form-field">
608
+ <td><label><b><?php _e( 'Last Name', 'email-subscribers' ); ?></b></label></td>
609
+ <td><input type="text" class="ig-es-contact-last-name" id="ig-es-contact-last-name" name="contact_data[last_name]" value="<?php echo $last_name; ?>"/></td>
610
+ </tr>
611
+
612
+ <tr class="form-field">
613
+ <td><label><b><?php _e( 'Email', 'email-subscribers' ); ?></b></label></td>
614
+ <td><input type="email" id="email" name="contact_data[email]" value="<?php echo $email; ?>"/></td>
615
+ </tr>
616
+
617
+ <?php if ( $is_new ) { ?>
618
+ <tr class="form-field">
619
+ <td><label><b><?php _e( 'Send Welcome Email?', 'email-subscribers' ); ?></b></label></td>
620
+ <td><input type="checkbox" id="ig-es-contact-welcome-email" name="contact_data[send_welcome_email]" <?php if ( $send_welcome_email ) {
621
+ echo "checked='checked'";
622
+ } ?> /></td>
623
+ </tr>
624
+ <?php } ?>
625
+ <tr class="form-field">
626
+ <td><label><b><?php _e( 'List(s)', 'email-subscribers' ); ?></b></label></td>
627
+ <td>
628
+ <table><?php echo $list_html; ?></table>
629
+ </td>
630
+ </tr>
631
+ <tr class="form-field">
632
+ <td></td>
633
+ <td>
634
+ <input type="hidden" name="contact_data[created_at]" value="<?php echo $created; ?>"/>
635
+ <input type="hidden" name="contact_data[guid]" value="<?php echo $guid; ?>"/>
636
+ <input type="hidden" name="submitted" value="submitted"/>
637
+ <input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e( 'Save Changes', 'email-subscribers' ); ?>"/>
638
+ </td>
639
+ </tr>
640
+ </tbody>
641
+ </table>
642
+ </form>
643
+ <?php
644
+ }
645
+
646
+
647
+ /**
648
+ * Returns the count of records in the database.
649
+ *
650
+ * @return null|string
651
+ */
652
+ public static function record_count() {
653
+ global $wpdb;
654
+
655
+ $sql = "SELECT COUNT(*) FROM " . IG_CONTACTS_TABLE;
656
+
657
+ return $wpdb->get_var( $sql );
658
+ }
659
+
660
+
661
+ /** Text displayed when no subscriber data is available */
662
+
663
+
664
+ /**
665
+ * Render a column when no column specific method exist.
666
+ *
667
+ * @param array $item
668
+ * @param string $column_name
669
+ *
670
+ * @return mixed
671
+ */
672
+ public function column_default( $item, $column_name ) {
673
+ $item = apply_filters( 'es_subscribers_col_data', $item, $column_name );
674
+ switch ( $column_name ) {
675
+ case 'lists':
676
+ return $this->get_lists_to_show( $item['id'] );
677
+ case 'created_at':
678
+ return ig_es_format_date_time( $item[ $column_name ] );
679
+ case 'first_name':
680
+ case 'email':
681
+ default:
682
+ return $item[ $column_name ]; //Show the whole array for troubleshooting purposes
683
+ }
684
+ }
685
+
686
+ public function get_lists_to_show( $contact_id ) {
687
+
688
+ $list_str = '';
689
+
690
+ if ( isset( $this->contact_lists_statuses[ $contact_id ] ) ) {
691
+
692
+ $lists = $this->contact_lists_statuses[ $contact_id ];
693
+
694
+ if ( count( $lists ) > 0 ) {
695
+ // Show only 4 lists
696
+ //$contact_lists_to_display = array_slice( $lists, 0, 4 );
697
+ foreach ( $lists as $list_id => $status ) {
698
+ if ( ! empty( $this->lists_id_name_map[ $list_id ] ) ) {
699
+ $list_str .= '<span class="es_list_contact_status ' . strtolower( $status ) . '" title="' . ucwords( $status ) . '">' . $this->lists_id_name_map[ $list_id ] . '</span> ';
700
+ }
701
+ }
702
+ }
703
+ }
704
+
705
+ return $list_str;
706
+ }
707
+
708
+ public function status_label_map( $status ) {
709
+
710
+ $statuses = array(
711
+ // 'confirmed' => __( 'Confirmed', 'email-subscribers' ),
712
+ 'subscribed' => __( 'Subscribed', 'email-subscribers' ),
713
+ 'unconfirmed' => __( 'Unconfirmed', 'email-subscribers' ),
714
+ 'unsubscribed' => __( 'Unsubscribed', 'email-subscribers' ),
715
+ // 'single_opt_in' => __( 'Single Opt In', 'email-subscribers' ),
716
+ // 'double_opt_in' => __( 'Double Opt In', 'email-subscribers' )
717
+ );
718
+
719
+
720
+ if ( ! in_array( $status, array_keys( $statuses ) ) ) {
721
+ return '';
722
+ }
723
+
724
+ return $statuses[ $status ];
725
+ }
726
+
727
+ /**
728
+ * Render the bulk edit checkbox
729
+ *
730
+ * @param array $item
731
+ *
732
+ * @return string
733
+ */
734
+ function column_cb( $item ) {
735
+ return sprintf(
736
+ '<input type="checkbox" name="subscribers[]" value="%s"/>', $item['id']
737
+ );
738
+ }
739
+
740
+
741
+ /**
742
+ * Method for name column
743
+ *
744
+ * @param array $item an array of DB data
745
+ *
746
+ * @return string
747
+ */
748
+ function column_name( $item ) {
749
+ $delete_nonce = wp_create_nonce( 'ig_es_delete_subscriber' );
750
+
751
+ $name = ES_Common::prepare_name_from_first_name_last_name( $item['first_name'], $item['last_name'] );
752
+ $title = '<strong>' . $name . '</strong>';
753
+
754
+ $page = ig_es_get_request_data( 'page' );
755
+
756
+ $actions = array(
757
+ 'edit' => sprintf( __( '<a href="?page=%s&action=%s&subscriber=%s&_wpnonce=%s">Edit</a>', 'email-subscribers' ), esc_attr( $page ), 'edit', absint( $item['id'] ), $delete_nonce ),
758
+ 'delete' => sprintf( __( '<a href="?page=%s&action=%s&subscriber=%s&_wpnonce=%s" onclick="return checkDelete()">Delete</a>', 'email-subscribers' ), esc_attr( $page ), 'delete', absint( $item['id'] ), $delete_nonce ),
759
+ );
760
+
761
+ $optin_type = get_option( 'ig_es_optin_type' );
762
+
763
+ //if ( in_array( $optin_type, array( 'double_optin', 'double_opt_in' ) ) ) {
764
+ $actions['resend'] = sprintf( __( '<a href="?page=%s&action=%s&subscriber=%s&_wpnonce=%s">Resend Confirmation<a>', 'email-subscribers' ), esc_attr( ig_es_get_request_data( 'page' ) ), 'resend', absint( $item['id'] ), $delete_nonce );
765
+
766
+ //}
767
+
768
+ return $title . $this->row_actions( $actions );
769
+ }
770
+
771
+
772
+ /**
773
+ * Associative array of columns
774
+ *
775
+ * @return array
776
+ */
777
+ function get_columns() {
778
+ $columns = array(
779
+ 'cb' => '<input type="checkbox"/>',
780
+ 'name' => __( 'Name', 'email-subscribers' ),
781
+ 'email' => __( 'Email', 'email-subscribers' ),
782
+ 'lists' => __( 'List(s)', 'email-subscribers' ),
783
+ 'created_at' => __( 'Created', 'email-subscribers' ),
784
+ );
785
+
786
+ return $columns;
787
+ }
788
+
789
+ /**
790
+ * Columns to make sortable.
791
+ *
792
+ * @return array
793
+ */
794
+ public function get_sortable_columns() {
795
+ $sortable_columns = array(
796
+ 'name' => array( 'first_name', true ),
797
+ 'email' => array( 'email', false ),
798
+ // 'status' => array( 'status', false ),
799
+ 'created_at' => array( 'created_at', false )
800
+ );
801
+
802
+ return $sortable_columns;
803
+ }
804
+
805
+ /**
806
+ * Returns an associative array containing the bulk action
807
+ *
808
+ * @return array
809
+ */
810
+ public function get_bulk_actions() {
811
+ $actions = array(
812
+ 'bulk_delete' => __( 'Delete', 'email-subscribers' ),
813
+ 'bulk_list_update' => __( 'Move To List', 'email-subscribers' ),
814
+ 'bulk_list_add' => __( 'Add To List', 'email-subscribers' ),
815
+ 'bulk_status_update' => __( 'Change Status', 'email-subscribers' )
816
+ );
817
+
818
+ return $actions;
819
+ }
820
+
821
+
822
+ public function search_box( $text, $input_id ) {
823
+
824
+ ?>
825
+ <p class="search-box box-ma10">
826
+ <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
827
+ <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>"/>
828
+ <?php submit_button( __( 'Search Contacts', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
829
+ </p>
830
+ <p class="search-box search-group-box box-ma10">
831
+ <?php $filter_by_status = ig_es_get_request_data( 'filter_by_status' ); ?>
832
+ <select name="filter_by_status">
833
+ <?php echo ES_Common::prepare_statuses_dropdown_options( $filter_by_status, __( 'All Statuses', 'email-subscribers' ) ); ?>
834
+ </select>
835
+ </p>
836
+ <p class="search-box search-group-box box-ma10">
837
+ <?php $filter_by_list_id = ig_es_get_request_data( 'filter_by_list_id' ); ?>
838
+ <select name="filter_by_list_id">
839
+ <?php echo ES_Common::prepare_list_dropdown_options( $filter_by_list_id, __( 'All Lists', 'email-subscribers' ) ); ?>
840
+ </select>
841
+ </p>
842
+
843
+ <?php }
844
+
845
+
846
+ /**
847
+ * Handles data query and filter, sorting, and pagination.
848
+ */
849
+ public function prepare_items() {
850
+
851
+ $this->_column_headers = $this->get_column_info();
852
+
853
+ /** Process bulk action */
854
+ $this->process_bulk_action();
855
+ $this->search_box( ig_es_get_request_data( 's' ), 'subscriber-search-input' );
856
+ $this->prepare_lists_dropdown();
857
+ $this->prepare_statuses_dropdown();
858
+
859
+ $per_page = $this->get_items_per_page( self::$option_per_page, 200 );
860
+ $current_page = $this->get_pagenum();
861
+ $total_items = $this->get_subscribers( 0, 0, true );
862
+
863
+ $this->set_pagination_args( array(
864
+ 'total_items' => $total_items, //WE have to calculate the total number of items
865
+ 'per_page' => $per_page //WE have to determine how many items to show on a page
866
+ ) );
867
+
868
+ $contacts = $this->get_subscribers( $per_page, $current_page );
869
+
870
+
871
+ $this->items = $contacts;
872
+
873
+ if ( count( $contacts ) > 0 ) {
874
+
875
+ $contact_ids = array_map( array( $this, 'get_contact_id' ), $contacts );
876
+
877
+ $contact_lists_statuses = ES_DB_Lists_Contacts::get_list_status_by_contact_ids( $contact_ids );
878
+
879
+ $this->contact_lists_statuses = $contact_lists_statuses;
880
+
881
+ $lists_id_name_map = ES()->lists_db->get_list_id_name_map();
882
+
883
+ $this->lists_id_name_map = $lists_id_name_map;
884
+
885
+ }
886
+ }
887
+
888
+ public function get_contact_id(
889
+ $contact
890
+ ) {
891
+ return $contact['id'];
892
+ }
893
+
894
+ public function prepare_lists_dropdown() {
895
+ $data = '<label for="bulk-action-selector-top" class="screen-reader-text">Select bulk action</label><select name="list_id" id="list_id" class="groupsselect" style="display: none">';
896
+ $data .= ES_Common::prepare_list_dropdown_options();
897
+ $data .= '</select>';
898
+
899
+ echo $data;
900
+ }
901
+
902
+ /**
903
+ * Edit Status
904
+ *
905
+ * @since 4.0.0
906
+ */
907
+ public function prepare_statuses_dropdown() {
908
+ $data = '<label for="bulk-action-selector-top" class="screen-reader-text">Select bulk action</label><select name="status_select" id="status_select" class="statusesselect" style="display:none;">';
909
+ $data .= ES_Common::prepare_statuses_dropdown_options();
910
+ $data .= '</select>';
911
+
912
+ echo $data;
913
+ }
914
+
915
+ /**
916
+ * Process Bulk Action
917
+ *
918
+ * @since 4.0.0
919
+ */
920
+ public function process_bulk_action() {
921
+
922
+ //Detect when a bulk action is being triggered...
923
+ if ( 'delete' === $this->current_action() ) {
924
+
925
+ // In our file that handles the request, verify the nonce.
926
+ $nonce = esc_attr( ig_es_get_request_data( '_wpnonce' ) );
927
+
928
+ if ( ! wp_verify_nonce( $nonce, 'ig_es_delete_subscriber' ) ) {
929
+ die( 'You do not have a permission to delete contact(s)' );
930
+ } else {
931
+ $subscriber_id = absint( ig_es_get_request_data( 'subscriber' ) );
932
+ $deleted = ES()->contacts_db->delete_contacts_by_ids( array( $subscriber_id ) );
933
+ if ( $deleted ) {
934
+ $message = __( 'Contact(s) have been deleted successfully!', 'email-subscribers' );
935
+ ES_Common::show_message( $message, 'success' );
936
+ }
937
+
938
+ return;
939
+ }
940
+
941
+ }
942
+
943
+ if ( 'resend' === $this->current_action() ) {
944
+ // In our file that handles the request, verify the nonce.
945
+ $nonce = esc_attr( ig_es_get_request_data( '_wpnonce' ) );
946
+
947
+ if ( ! wp_verify_nonce( $nonce, 'ig_es_delete_subscriber' ) ) {
948
+ die( 'You do not have a permission to resend email confirmation' );
949
+ } else {
950
+ $id = absint( ig_es_get_request_data( 'subscriber' ) );
951
+ $resend = ig_es_get_request_data( 'resend', false );
952
+ $subscriber = ES()->contacts_db->get_by_id( $id );
953
+
954
+ $email = $subscriber['email'];
955
+ $merge_tags = array(
956
+ 'contact_id' => $subscriber['id'],
957
+ );
958
+
959
+ if ( $resend ) {
960
+ $message = __( 'Confirmation email has been sent successfully!', 'email-subscribers' );
961
+ ES_Common::show_message( $message, 'success' );
962
+ return;
963
+ }else{
964
+ $response = ES()->mailer->send_double_optin_email( $email, $merge_tags );
965
+ $url = add_query_arg( 'resend', true );
966
+ //redirect to resend link and avoid resending email
967
+ ?>
968
+ <meta http-equiv="refresh" content="0; url=<?php echo $url; ?>"/>
969
+ <?php
970
+ }
971
+
972
+ return;
973
+
974
+ }
975
+
976
+ }
977
+
978
+ $action = ig_es_get_request_data( 'action' );
979
+ $action2 = ig_es_get_request_data( 'action2' );
980
+
981
+ $actions = array( 'bulk_delete', 'bulk_status_update', 'bulk_list_update', 'bulk_list_add' );
982
+ if ( in_array( $action, $actions ) || in_array( $action2, $actions ) ) {
983
+
984
+ $subscriber_ids = ig_es_get_request_data( 'subscribers' );
985
+ if ( empty( $subscriber_ids ) ) {
986
+ $message = __( 'Please select subscribers to update.', 'email-subscribers' );
987
+ ES_Common::show_message( $message, 'error' );
988
+
989
+ return;
990
+ }
991
+
992
+ // If the delete bulk action is triggered
993
+ if ( ( 'bulk_delete' === $action ) || ( 'bulk_delete' === $action2 ) ) {
994
+
995
+ $deleted = ES()->contacts_db->delete_contacts_by_ids( $subscriber_ids );
996
+
997
+ if ( $deleted ) {
998
+ $message = __( 'Contact(s) have been deleted successfully!', 'email-subscribers' );
999
+ ES_Common::show_message( $message, 'success' );
1000
+ }
1001
+
1002
+ return;
1003
+ }
1004
+
1005
+ if ( ( 'bulk_status_update' === $action ) || ( 'bulk_status_update' === $action2 ) ) {
1006
+ $status = ig_es_get_request_data( 'status_select' );
1007
+
1008
+ if ( empty( $status ) ) {
1009
+ $message = __( 'Please select status.', 'email-subscribers' );
1010
+ ES_Common::show_message( $message, 'error' );
1011
+
1012
+ return;
1013
+ }
1014
+
1015
+ // loop over the array of record IDs and delete them
1016
+ $edited = ES_DB_Lists_Contacts::edit_subscriber_status( $subscriber_ids, $status );
1017
+
1018
+ if ( $edited ) {
1019
+ $message = __( 'Status has been changed successfully!', 'email-subscribers' );
1020
+ ES_Common::show_message( $message, 'success' );
1021
+ }
1022
+
1023
+ return;
1024
+ }
1025
+
1026
+ if ( ( 'bulk_list_update' === $action ) || ( 'bulk_list_update' === $action2 ) ) {
1027
+
1028
+ $list_id = ig_es_get_request_data( 'list_id' );
1029
+ if ( empty( $list_id ) ) {
1030
+ $message = __( 'Please select list.', 'email-subscribers' );
1031
+ ES_Common::show_message( $message, 'error' );
1032
+
1033
+ return;
1034
+ }
1035
+
1036
+ $edited = ES()->contacts_db->update_contacts_list( $subscriber_ids, $list_id );
1037
+
1038
+ if ( $edited ) {
1039
+ $message = __( 'Contact(s) have been moved to list successfully!', 'email-subscribers' );
1040
+ ES_Common::show_message( $message, 'success' );
1041
+ }
1042
+
1043
+ return;
1044
+ }
1045
+
1046
+ if ( ( 'bulk_list_add' === $action ) || ( 'bulk_list_add' === $action2 ) ) {
1047
+
1048
+ $list_id = ig_es_get_request_data( 'list_id' );
1049
+
1050
+ if ( empty( $list_id ) ) {
1051
+ $message = __( 'Please select list.', 'email-subscribers' );
1052
+ ES_Common::show_message( $message, 'error' );
1053
+
1054
+ return;
1055
+ }
1056
+
1057
+ $edited = ES()->contacts_db->add_contacts_to_list( $subscriber_ids, $list_id );
1058
+
1059
+ if ( $edited ) {
1060
+ $message = __( 'Contact(s) have been added to list successfully!', 'email-subscribers' );
1061
+ ES_Common::show_message( $message, 'success' );
1062
+ }
1063
+
1064
+ return;
1065
+ }
1066
+ }
1067
+ }
1068
+
1069
+ /**
1070
+ * Remove contacts from list when list is deleted
1071
+ *
1072
+ * @param $list_ids
1073
+ *
1074
+ * @since 4.3.1
1075
+ */
1076
+ public function delete_contacts_from_list( $list_id ) {
1077
+ global $wpdb;
1078
+
1079
+ $ig_lists_contacts_table = IG_LISTS_CONTACTS_TABLE;
1080
+
1081
+ $query = "DELETE FROM {$ig_lists_contacts_table} WHERE list_id = %d";
1082
+
1083
+ $wpdb->query( $wpdb->prepare( $query, $list_id ) );
1084
+ }
1085
+
1086
+ /**
1087
+ * Set form_id = 0 as Form is already deleted
1088
+ *
1089
+ * @param $form_id
1090
+ *
1091
+ * @since 4.3.1
1092
+ */
1093
+ public function set_default_form_id( $form_id ) {
1094
+
1095
+ global $wpdb;
1096
+
1097
+ $ig_contacts_table = IG_CONTACTS_TABLE;
1098
+
1099
+ $query = "UPDATE $ig_contacts_table SET form_id = 0 WHERE form_id = %d";
1100
+
1101
+ $wpdb->query( $wpdb->prepare( $query, $form_id ) );
1102
+
1103
+ }
1104
+
1105
+ public function no_items() {
1106
+ _e( 'No contacts avaliable.', 'email-subscribers' );
1107
+ }
1108
+
1109
+
1110
+ }
lite/includes/classes/class-es-cron.php ADDED
@@ -0,0 +1,438 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ class ES_Cron {
9
+ /**
10
+ * ES_Cron constructor.
11
+ *
12
+ * @since 4.0.0
13
+ */
14
+ public function __construct() {
15
+ add_action( 'wp_loaded', array( &$this, 'init' ), 1 );
16
+ add_action( 'ig_es_plugin_deactivate', array( &$this, 'clear' ) );
17
+ }
18
+
19
+ /**
20
+ * Initialize Cron
21
+ *
22
+ * @since 4.3.1
23
+ */
24
+ public function init() {
25
+
26
+ add_filter( 'cron_schedules', array( &$this, 'cron_schedules' ) );
27
+
28
+ // Not using anymore...remain for backward compatibility to avoid PHP warnings.
29
+ add_action( 'ig_es_cron_fifteen_mins', array( &$this, 'ig_es_cron_fifteen_mins_callback' ), 10, 2 );
30
+
31
+ add_action( 'ig_es_cron', array( &$this, 'hourly' ) );
32
+ add_action( 'ig_es_cron_worker', array( &$this, 'handler' ), - 1 );
33
+
34
+ if ( ! wp_next_scheduled( 'ig_es_cron' ) ) {
35
+ $this->update( true );
36
+ }
37
+
38
+ $this->handle_cron_request();
39
+ }
40
+
41
+ public function ig_es_cron_fifteen_mins_callback( $es = '', $guid = '' ) {
42
+ /**
43
+ * We are not using ig_es_cron_fifteen_mins action anymore.
44
+ *
45
+ * This function was attached to ig_es_cron_fifteen_mins cron
46
+ *
47
+ * @since 4.3.1
48
+ */
49
+ }
50
+
51
+
52
+ /**
53
+ * Schedule/ Clear Cronjob
54
+ *
55
+ * @param bool $hourly_only
56
+ *
57
+ * @return bool
58
+ *
59
+ * @since 4.3.1
60
+ */
61
+ public function update( $hourly_only = false ) {
62
+
63
+ // Schedule Main Cron
64
+ if ( ! wp_next_scheduled( 'ig_es_cron' ) ) {
65
+ wp_schedule_event( strtotime( 'midnight' ) - 300, 'hourly', 'ig_es_cron' );
66
+
67
+ return true;
68
+ } elseif ( $hourly_only ) {
69
+ return false;
70
+ }
71
+
72
+ $ig_es_disable_wp_cron = get_option( 'ig_es_disable_wp_cron', 'no' );
73
+
74
+ // Don't want to use WP_CRON?
75
+ if ( 'yes' === $ig_es_disable_wp_cron ) {
76
+ $this->clear();
77
+
78
+ return true;
79
+ }
80
+
81
+ $this->schedule();
82
+
83
+ return false;
84
+ }
85
+
86
+ /**
87
+ * Update Crons every hour
88
+ *
89
+ * @since 4.3.1
90
+ */
91
+ public function hourly() {
92
+ $this->update();
93
+ }
94
+
95
+ /**
96
+ * Schedule Events if it's not already scheduled
97
+ *
98
+ * @since 4.3.1
99
+ */
100
+ public function schedule() {
101
+
102
+ // Add worker only once
103
+ if ( ! wp_next_scheduled( 'ig_es_cron_auto_responder' ) ) {
104
+ wp_schedule_event( floor( time() / 300 ) * 300 - 120, 'ig_es_cron_interval', 'ig_es_cron_auto_responder' );
105
+ }
106
+
107
+ if ( ! wp_next_scheduled( 'ig_es_cron_worker' ) ) {
108
+ wp_schedule_event( floor( time() / 300 ) * 300, 'ig_es_cron_interval', 'ig_es_cron_worker' );
109
+ }
110
+
111
+ }
112
+
113
+ /**
114
+ * Clear all ES Cronjob
115
+ *
116
+ * @since 4.3.1
117
+ */
118
+ public function clear() {
119
+ wp_clear_scheduled_hook( 'ig_es_cron' );
120
+ wp_clear_scheduled_hook( 'ig_es_cron_worker' );
121
+ wp_clear_scheduled_hook( 'ig_es_cron_auto_responder' );
122
+
123
+ $cron_url = $this->url();
124
+ if ( ! empty( $cron_url ) ) {
125
+ parse_str( $cron_url, $output );
126
+ $guid = $output['guid'];
127
+ wp_clear_scheduled_hook( 'ig_es_cron_fifteen_mins', array( 'cron', $guid ) );
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Lock Cron to avoid multiple execution of a cron
133
+ *
134
+ * @param int $key
135
+ *
136
+ * @return bool
137
+ *
138
+ * @since 4.3.1
139
+ */
140
+ public function lock( $key = 0 ) {
141
+
142
+ $process_id = get_option( 'ig_es_cron_lock_' . $key, false );
143
+
144
+ if ( $process_id && $this->is_locked( $key ) ) {
145
+ return $process_id;
146
+ }
147
+
148
+ $process_id = @getmypid();
149
+
150
+ update_option( 'ig_es_cron_lock_' . $key, $process_id, false );
151
+
152
+ return true;
153
+ }
154
+
155
+ /**
156
+ * Unlock Cron
157
+ *
158
+ * @param int $key
159
+ *
160
+ * @since 4.3.1
161
+ */
162
+ public function unlock( $key = 0 ) {
163
+ update_option( 'ig_es_cron_lock_' . $key, false, false );
164
+ }
165
+
166
+ /**
167
+ * Check If Cron Locked
168
+ *
169
+ * @param $key
170
+ *
171
+ * @return bool
172
+ *
173
+ * @since 4.3.1
174
+ */
175
+ public function is_locked( $key = 0 ) {
176
+ global $wpdb;
177
+
178
+ $sql = "SELECT COUNT(*) FROM {$wpdb->prefix}options WHERE option_name LIKE %s AND option_value != ''";
179
+
180
+ $res = $wpdb->get_var( $wpdb->prepare( $sql, 'ig_es_cron_lock_' . $key . '%' ) );
181
+
182
+ return ! ! $res;
183
+ }
184
+
185
+ /**
186
+ * Set interval for Email Subscribers Cronjob
187
+ *
188
+ * @return mixed
189
+ *
190
+ * @since 4.3.1
191
+ * @since 4.3.2 Changed name from filter_cron_schedules to cron_schedules
192
+ */
193
+ public function cron_schedules( $schedules = array() ) {
194
+
195
+ $schedules['ig_es_cron_interval'] = array(
196
+ 'interval' => IG_ES_CRON_INTERVAL,
197
+ 'display' => esc_html__( 'Email Subscribers Cronjob Interval' ),
198
+ );
199
+
200
+ return $schedules;
201
+ }
202
+
203
+ /**
204
+ * Get Cron URL
205
+ *
206
+ * @param bool $self
207
+ * @param bool $pro
208
+ * @param string $campaign_hash
209
+ *
210
+ * @return mixed|string|void
211
+ *
212
+ * @since 4.3.1
213
+ */
214
+ public function url( $self = false, $pro = false, $campaign_hash = '' ) {
215
+
216
+ $cron_url = get_option( 'ig_es_cronurl', '' );
217
+
218
+ $result = array();
219
+ if ( ! empty( $cron_url ) ) {
220
+ parse_str( $cron_url, $result );
221
+ }
222
+
223
+ $cron_url = add_query_arg( 'es', 'cron', site_url() );
224
+ if ( empty( $result['guid'] ) ) {
225
+ $guid = ES_Common::generate_guid();
226
+ } else {
227
+ $guid = $result['guid'];
228
+ }
229
+
230
+ $cron_url = add_query_arg( 'guid', $guid, $cron_url );
231
+ update_option( 'ig_es_cronurl', $cron_url );
232
+
233
+ if ( ! empty( $campaign_hash ) ) {
234
+ $cron_url = add_query_arg( 'campaign_hash', $campaign_hash, $cron_url );
235
+ }
236
+
237
+ if ( $self ) {
238
+ $cron_url = add_query_arg( 'self', true, $cron_url );
239
+ $nonce = wp_create_nonce( 'ig_es_self_cron' );
240
+ $cron_url = add_query_arg( '_wpnonce', $nonce, $cron_url );
241
+ }
242
+
243
+ if ( $pro ) {
244
+ $cron_url = add_query_arg( 'es_pro', true, $cron_url );
245
+ }
246
+
247
+ return $cron_url;
248
+ }
249
+
250
+ /**
251
+ * Handler
252
+ *
253
+ * @return bool
254
+ *
255
+ * @since 4.3.1
256
+ */
257
+ public function handler() {
258
+
259
+ if ( defined( 'IG_ES_DOING_CRON' ) || defined( 'DOING_AJAX' ) || defined( 'DOING_AUTOSAVE' ) || defined( 'WP_INSTALLING' ) || defined( 'MAILSTER_DO_UPDATE' ) ) {
260
+ return false;
261
+ }
262
+
263
+ define( 'IG_ES_DOING_CRON', microtime( true ) );
264
+
265
+ register_shutdown_function( array( &$this, 'shutdown' ) );
266
+ }
267
+
268
+ /**
269
+ * Handle Shutdown event
270
+ *
271
+ * @since 4.3.1
272
+ */
273
+ public function shutdown() {
274
+
275
+ if ( ! defined( 'IG_ES_DOING_CRON' ) ) {
276
+ return;
277
+ }
278
+
279
+ // Unlock Cron Lock
280
+ $this->unlock();
281
+ }
282
+
283
+ /**
284
+ * Handle Cron Request
285
+ *
286
+ * @since 4.0.0
287
+ *
288
+ * @modify 4.3.1
289
+ */
290
+ public function handle_cron_request() {
291
+
292
+ $execution_start_time = microtime( true );
293
+
294
+ $es_request = ig_es_get_request_data( 'es' );
295
+ $guid = ig_es_get_request_data( 'guid' );
296
+
297
+ // It's not a cron request . Say Goodbye!
298
+ if ( 'cron' !== $es_request ) {
299
+ return;
300
+ }
301
+
302
+ $self = ig_es_get_request_data( 'self', 0 );
303
+
304
+ if ( ! $this->is_locked() && ( $self == 0 || ( $self == 1 && wp_verify_nonce( ig_es_get_request_data( '_wpnonce' ), 'ig_es_self_cron' ) ) ) ) {
305
+
306
+ if ( ! empty( $guid ) ) {
307
+
308
+ $response = array( 'status' => 'SUCCESS', 'es_remaining_email_count' => 100 );
309
+
310
+ $es_process_request = true;
311
+
312
+ // filter request
313
+ $es_process_request = apply_filters( 'ig_es_email_sending_limit', $es_process_request );
314
+
315
+ if ( true === $es_process_request ) {
316
+ $security1 = strlen( $guid );
317
+ $es_c_cronguid_noslash = str_replace( "-", "", $guid );
318
+ $security2 = strlen( $es_c_cronguid_noslash );
319
+ if ( $security1 == 34 && $security2 == 30 ) {
320
+ if ( ! preg_match( '/[^a-z]/', $es_c_cronguid_noslash ) ) {
321
+ $cron_url = ES()->cron->url();
322
+
323
+ parse_str( $cron_url, $output );
324
+
325
+ // Now, all check pass.
326
+ if ( $guid === $output['guid'] ) {
327
+
328
+ // Release WP_CRON if it should
329
+ if ( wp_next_scheduled( 'ig_es_cron' ) - $execution_start_time < 0 ) {
330
+ spawn_cron();
331
+ }
332
+
333
+ // Lock Cron to avoid duplicate
334
+ $this->lock();
335
+
336
+ // Queue Auto Responder
337
+ do_action( 'ig_es_cron_auto_responder' );
338
+
339
+ // Worker
340
+ do_action( 'ig_es_cron_worker' );
341
+
342
+ $response['total_emails_sent'] = get_transient( 'ig_es_total_emails_sent' );
343
+ $response['es_remaining_email_count'] = get_transient( 'ig_es_remaining_email_count' );
344
+ $response['message'] = 'EMAILS_SENT';
345
+ $response['status'] = 'SUCCESS';
346
+
347
+ // Unlock it.
348
+ $this->unlock();
349
+
350
+ } else {
351
+ $self = false;
352
+ $response['status'] = 'ERROR';
353
+ $response['message'] = 'CRON_GUID_DOES_NOT_MATCH';
354
+ }
355
+ } else {
356
+ $self = false;
357
+ $response['status'] = 'ERROR';
358
+ $response['message'] = 'CRON_GUID_PATTERN_DOES_NOT_MATCH';
359
+ }
360
+ } else {
361
+ $self = false;
362
+ $response['status'] = 'ERROR';
363
+ $response['message'] = 'INVALID_CRON_GUID';
364
+ }
365
+ } else {
366
+ $self = false;
367
+ $response['status'] = 'ERROR';
368
+ $response['message'] = 'DO_NOT_PROCESS_REQUEST';
369
+ }
370
+ } else {
371
+ $self = false;
372
+ $response['status'] = 'ERROR';
373
+ $response['message'] = 'EMPTY_CRON_GUID';
374
+ }
375
+
376
+ } else {
377
+ $response['es_remaining_email_count'] = 0;
378
+ $response['message'] = 'PLEASE_TRY_AGAIN_LATER';
379
+ $response['status'] = 'ERROR';
380
+ }
381
+
382
+ if ( $self ) {
383
+
384
+ $total_emails_sent = ! empty( $response['total_emails_sent'] ) ? $response['total_emails_sent'] : 0;
385
+ $status = ! empty( $response['status'] ) ? $response['status'] : 'ERROR';
386
+ $total_emails_to_be_sent = ! empty( $response['es_remaining_email_count'] ) ? $response['es_remaining_email_count'] : 0;
387
+ $cron_url = ES()->cron->url( true );
388
+
389
+ $send_now_text = __( sprintf( "<a href='%s'>Send Now</a>", $cron_url ), 'email-subscribers' );
390
+
391
+ if ( 'SUCCESS' === $status ) {
392
+ $message = __( sprintf( 'Email(s) have been sent successfully!' ), 'email-subscribers' );
393
+ } else {
394
+ $message = $this->get_status_messages( $response['message'] );
395
+ }
396
+
397
+ include ES_PLUGIN_DIR . 'lite/public/partials/cron-message.php';
398
+ die();
399
+ } else {
400
+ echo json_encode( $response );
401
+ die();
402
+ }
403
+ }
404
+
405
+ /**
406
+ * Get Status Message
407
+ *
408
+ * @param string $message
409
+ *
410
+ * @return mixed|string
411
+ *
412
+ * @since 4.0.0
413
+ */
414
+ public function get_status_messages( $message = '' ) {
415
+
416
+ if ( empty( $message ) ) {
417
+ return '';
418
+ }
419
+
420
+ $status_messages = array(
421
+ 'EMAILS_SENT' => __( 'Emails sent successfully!', 'email-subscribers' ),
422
+ 'EMAILS_NOT_FOUND' => __( 'Emails not found.', 'email-subscribers' ),
423
+ 'NOTIFICATION_NOT_FOUND' => __( 'No notifications found to send.', 'email-subscribers' ),
424
+ 'CRON_GUID_DOES_NOT_MATCH' => __( 'Invalid GUID.', 'email-subscribers' ),
425
+ 'CRON_GUID_PATTERN_DOES_NOT_MATCH' => __( 'Invalid GUID.', 'email-subscribers' ),
426
+ 'INVALID_CRON_GUID' => __( 'Invalid GUID.', 'email-subscribers' ),
427
+ 'DO_NOT_PROCESS_REQUEST' => __( 'Not allowed to process request.', 'email-subscribers' ),
428
+ 'EMPTY_CRON_GUID' => __( 'GUID is empty.', 'email-subscribers' ),
429
+ 'PLEASE_TRY_AGAIN_LATER' => __( 'Please try after sometime.', 'email-subscribers' ),
430
+ 'EMAIL_SENDING_LIMIT_EXCEEDED' => __( 'You have hit your hourly email sending limit. Please try after sometime.', 'email-subscribers' ),
431
+ );
432
+
433
+ $message_text = ! empty( $status_messages[ $message ] ) ? $status_messages[ $message ] : '';
434
+
435
+ return $message_text;
436
+ }
437
+
438
+ }
lite/includes/classes/class-es-export-subscribers.php ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * CSV Exporter bootstrap file
10
+ */
11
+ class Export_Subscribers {
12
+
13
+ /**
14
+ * Constructor
15
+ */
16
+ public function __construct() {
17
+
18
+ $report = ig_es_get_request_data( 'report' );
19
+ $status = ig_es_get_request_data( 'status' );
20
+
21
+ $can_access = ES_Common::ig_es_can_access( 'audience' );
22
+
23
+ if ( $report && $status && $can_access ) {
24
+
25
+ $status = trim( $status );
26
+
27
+ $selected_list_id = 0;
28
+
29
+ if ( 'select_list' === $status ) {
30
+ $selected_list_id = ig_es_get_request_data( 'list_id', 0 );
31
+
32
+ if ( 0 === $selected_list_id ) {
33
+ $message = __( "Please Select List", "email-subscribers" );
34
+ ES_Common::show_message( $message, 'error' );
35
+ exit();
36
+ }
37
+ }
38
+
39
+ $csv = $this->generate_csv( $status, $selected_list_id );
40
+
41
+ $file_name = strtolower( $status ) . '-' . 'contacts.csv';
42
+
43
+ if ( empty( $csv ) ) {
44
+ $message = __( "No data available", 'email-subscribers' );
45
+ ES_Common::show_message( $message, 'error' );
46
+ exit();
47
+ } else {
48
+ header( "Pragma: public" );
49
+ header( "Expires: 0" );
50
+ header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
51
+ header( "Cache-Control: private", false );
52
+ header( "Content-Type: application/octet-stream" );
53
+ header( "Content-Disposition: attachment; filename={$file_name};" );
54
+ header( "Content-Transfer-Encoding: binary" );
55
+
56
+ echo $csv;
57
+ exit;
58
+ }
59
+ }
60
+
61
+ add_filter( 'query_vars', array( $this, 'query_vars' ) );
62
+ add_action( 'parse_request', array( $this, 'parse_request' ) );
63
+ add_action( 'admin_menu', array( $this, 'plugin_menu' ) );
64
+ }
65
+
66
+ public function plugin_menu() {
67
+ add_submenu_page( null, 'Export Contacts', __( 'Export Contacts', 'email-subscribers' ), 'edit_posts', 'es_export_subscribers', array( $this, 'export_subscribers_page' ) );
68
+ }
69
+
70
+ public function prepare_header_footer_row() {
71
+
72
+ ?>
73
+
74
+ <tr>
75
+ <th scope="col"><?php _e( 'No.', 'email-subscribers' ); ?></th>
76
+ <th scope="col"><?php _e( 'Contacts', 'email-subscribers' ); ?></th>
77
+ <th scope="col"><?php _e( 'Total Contacts', 'email-subscribers' ); ?></th>
78
+ <th scope="col"><?php _e( 'Export', 'email-subscribers' ); ?></th>
79
+ </tr>
80
+
81
+ <?php
82
+ }
83
+
84
+ public function prepare_body() {
85
+
86
+ $list_dropdown_html = "<select name='list_id' id='ig_es_export_list_dropdown'>";
87
+ $list_dropdown_html .= ES_Common::prepare_list_dropdown_options();
88
+ $list_dropdown_html .= "</select>";
89
+
90
+ $export_lists = array(
91
+
92
+ 'all' => __( 'All Contacts', 'email-subscribers' ),
93
+ 'subscribed' => __( 'Subscribed Contacts', 'email-subscribers' ),
94
+ 'unsubscribed' => __( 'Unsubscribed Contacts', 'email-subscribers' ),
95
+ //'confirmed' => __( 'Confirmed Contacts', 'email-subscribers' ),
96
+ 'unconfirmed' => __( 'Unconfirmed Contacts', 'email-subscribers' ),
97
+ 'select_list' => $list_dropdown_html
98
+ );
99
+
100
+ $i = 1;
101
+ foreach ( $export_lists as $key => $export_list ) {
102
+ $class = '';
103
+ if ( $i % 2 === 0 ) {
104
+ $class = 'alternate';
105
+ }
106
+
107
+ $url = "admin.php?page=download_report&report=users&status={$key}";
108
+
109
+ ?>
110
+
111
+ <tr class="<?php echo $class; ?>" id="ig_es_export_<?php echo $key; ?>">
112
+ <td><?php echo $i; ?></td>
113
+ <td><?php _e( $export_list, 'email-subscribers' ); ?></td>
114
+ <td class="ig_es_total_contacts"><?php echo $this->count_subscribers( $key ); ?></td>
115
+ <td><a href="<?php echo $url; ?>" id="ig_es_export_link_<?php echo $key; ?>"><?php _e( 'Download', 'email-subscribers' ); ?></a></td>
116
+ </tr>
117
+
118
+ <?php
119
+ $i ++;
120
+ }
121
+
122
+ }
123
+
124
+ public function export_subscribers_page() {
125
+
126
+ $audience_tab_main_navigation = array();
127
+ $active_tab = 'export';
128
+ $audience_tab_main_navigation = apply_filters( 'ig_es_audience_tab_main_navigation', $active_tab, $audience_tab_main_navigation );
129
+
130
+ ?>
131
+ <div class="wrap">
132
+ <h2 style="margin-bottom:1em;">
133
+ <?php _e( 'Audience > Export Contacts', 'email-subscribers' );
134
+ ES_Common::prepare_main_header_navigation( $audience_tab_main_navigation );
135
+ ?>
136
+ </h2>
137
+ <div class="tool-box">
138
+ <form name="frm_es_subscriberexport" method="post">
139
+ <table width="100%" class="widefat" id="straymanage">
140
+ <thead>
141
+ <?php $this->prepare_header_footer_row(); ?>
142
+ </thead>
143
+ <tbody>
144
+ <?php $this->prepare_body(); ?>
145
+ </tbody>
146
+ <tfoot>
147
+ <?php $this->prepare_header_footer_row(); ?>
148
+ </tfoot>
149
+ </table>
150
+ </form>
151
+ </div>
152
+ </div>
153
+ <?php }
154
+
155
+
156
+ /**
157
+ * @param string $status
158
+ *
159
+ * @return string|null
160
+ */
161
+ public function count_subscribers( $status = 'all' ) {
162
+
163
+ global $wpdb;
164
+
165
+ switch ( $status ) {
166
+ case 'all':
167
+ $sql = "SELECT COUNT(*) FROM " . IG_LISTS_CONTACTS_TABLE;
168
+ break;
169
+
170
+ case 'subscribed':
171
+ $sql = $wpdb->prepare( "SELECT COUNT(*) FROM " . IG_LISTS_CONTACTS_TABLE . " WHERE status = %s", 'subscribed' );
172
+ break;
173
+
174
+ case 'unsubscribed':
175
+ $sql = $wpdb->prepare( "SELECT COUNT(email) FROM " . IG_CONTACTS_TABLE . " WHERE status = %s", 'unsubscribed' );
176
+ break;
177
+
178
+ case 'confirmed':
179
+ $sql = $wpdb->prepare( "SELECT COUNT(*) FROM " . IG_LISTS_CONTACTS_TABLE . " WHERE status = %s AND optin_type = %d", 'subscribed', IG_DOUBLE_OPTIN );
180
+ break;
181
+
182
+ case 'unconfirmed':
183
+ $sql = $wpdb->prepare( "SELECT count(contact_id) FROM " . IG_LISTS_CONTACTS_TABLE . " WHERE status = %s", 'unconfirmed' );
184
+ break;
185
+
186
+ case 'select_list':
187
+ default:
188
+ return '-';
189
+ break;
190
+ }
191
+
192
+ return $wpdb->get_var( $sql );
193
+ }
194
+
195
+
196
+ /**
197
+ * Allow for custom query variables
198
+ */
199
+ public function query_vars( $query_vars ) {
200
+ $query_vars[] = 'download_report';
201
+
202
+ return $query_vars;
203
+ }
204
+
205
+ /**
206
+ * Parse the request
207
+ */
208
+ public function parse_request( &$wp ) {
209
+ if ( array_key_exists( 'download_report', $wp->query_vars ) ) {
210
+ $this->download_report();
211
+ exit;
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Download report
217
+ */
218
+ public function download_report() {
219
+ ?>
220
+
221
+ <div class="wrap">
222
+ <div id="icon-tools" class="icon32"></div>
223
+ <h2>Download Report</h2>
224
+ <p>
225
+ <a href="?page=download_report&report=users"><?php _e( 'Export the Subscribers', 'email-subscribers' ); ?></a>
226
+ </p>
227
+
228
+ <?php
229
+ }
230
+
231
+ /**
232
+ * Generate CSV
233
+ * first_name, last_name, email, status, list, subscribed_at, unsubscribed_at
234
+ *
235
+ * @param string $status
236
+ * @param string $list_id
237
+ *
238
+ * @return string
239
+ */
240
+ public function generate_csv( $status = 'all', $list_id = '' ) {
241
+
242
+ global $wpdb;
243
+
244
+ ini_set( 'memory_limit', IG_MAX_MEMORY_LIMIT );
245
+ set_time_limit( IG_SET_TIME_LIMIT );
246
+
247
+ $email_subscribe_table = IG_CONTACTS_TABLE;
248
+ $contact_lists_table = IG_LISTS_CONTACTS_TABLE;
249
+
250
+ if ( 'all' === $status ) {
251
+ $query = "SELECT * FROM " . IG_LISTS_CONTACTS_TABLE;
252
+ } elseif ( 'subscribed' === $status ) {
253
+ $query = $wpdb->prepare( "SELECT * FROM {$contact_lists_table} WHERE status = %s", 'subscribed' );
254
+ } elseif ( 'unsubscribed' === $status ) {
255
+ $query = $wpdb->prepare( "SELECT * FROM {$contact_lists_table} WHERE status = %s", 'unsubscribed' );
256
+ } elseif ( 'confirmed' === $status ) {
257
+ $query = $wpdb->prepare( "SELECT * FROM {$contact_lists_table} WHERE status = %s AND optin_type = %d ", 'subscribed', IG_DOUBLE_OPTIN );
258
+ } elseif ( 'unconfirmed' === $status ) {
259
+ $query = $wpdb->prepare( "SELECT * FROM {$contact_lists_table} WHERE status = %s", 'unconfirmed' );
260
+ } elseif ( 'select_list' === $status ) {
261
+ $query = $wpdb->prepare( "SELECT * FROM {$contact_lists_table} WHERE list_id = %d ", $list_id );
262
+ } else {
263
+ // If nothing comes, export only 10 contacts
264
+ $query = "SELECT * FROM " . IG_LISTS_CONTACTS_TABLE . " LIMIT 0, 10";
265
+ }
266
+
267
+ $subscribers = array();
268
+ $results = $wpdb->get_results( $query, ARRAY_A );
269
+
270
+ if ( count( $results ) > 0 ) {
271
+ $contact_list_map = array();
272
+ $contact_ids = array();
273
+ foreach ( $results as $result ) {
274
+
275
+ if ( ! in_array( $result['contact_id'], $contact_ids ) ) {
276
+ $contact_ids[] = $result['contact_id'];
277
+ }
278
+
279
+ $contact_list_map[ $result['contact_id'] ][] = array(
280
+ 'status' => $result['status'],
281
+ 'list_id' => $result['list_id'],
282
+ 'optin_type' => $result['optin_type']
283
+ );
284
+ }
285
+
286
+ $contact_ids_str = "'" . implode( "' , '", $contact_ids ) . "' ";
287
+
288
+ $query = "SELECT `id`, `first_name`, `last_name`, `email`, `created_at` FROM {$email_subscribe_table} WHERE id IN ({$contact_ids_str})";
289
+
290
+ $subscribers = $wpdb->get_results( $query, ARRAY_A );
291
+ }
292
+
293
+ $csv_output = '';
294
+ if ( count( $subscribers ) > 0 ) {
295
+
296
+ $headers = array(
297
+ __( 'First Name', 'email-subscribers' ),
298
+ __( 'Last Name', 'email-subscribers' ),
299
+ __( 'Email', 'email-subscribers' ),
300
+ __( 'List', 'email-subscribers' ),
301
+ __( 'Status', 'email-subscribers' ),
302
+ __( 'Opt-In Type', 'email-subscribers' ),
303
+ __( 'Created On', 'email-subscribers' )
304
+ );
305
+
306
+ $lists_id_name_map = ES()->lists_db->get_list_id_name_map();
307
+ $csv_output .= '"' . implode( '", "', $headers ) . '"';
308
+ $csv_output .= "\n";
309
+
310
+ foreach ( $subscribers as $key => $subscriber ) {
311
+
312
+ $data['first_name'] = trim( str_replace( '"', ' ', $subscriber['first_name'] ) );
313
+ $data['last_name'] = trim( str_replace( '"', ' ', $subscriber['last_name'] ) );
314
+ $data['email'] = trim( str_replace( '"', ' ', $subscriber['email'] ) );
315
+
316
+ $contact_id = $subscriber['id'];
317
+ if ( ! empty( $contact_list_map[ $contact_id ] ) ) {
318
+ foreach ( $contact_list_map[ $contact_id ] as $list_details ) {
319
+ $data['list'] = $lists_id_name_map[ $list_details['list_id'] ];
320
+ $data['status'] = ucfirst( $list_details['status'] );
321
+ $data['optin_type'] = ( $list_details['optin_type'] == 1 ) ? 'Single Opt-In' : 'Double Opt-In';
322
+ $data['created_at'] = $subscriber['created_at'];
323
+ $csv_output .= '"' . implode( '", "', $data ) . '"';
324
+ $csv_output .= "\n";
325
+ }
326
+ }
327
+ }
328
+ }
329
+
330
+ return $csv_output;
331
+ }
332
+
333
+ }
334
+
lite/includes/classes/class-es-form-widget.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ class ES_Form_Widget extends WP_Widget {
9
+
10
+ function __construct() {
11
+ parent::__construct( 'email-subscribers-form', __( 'Email Subscribers', 'email-subscribers' ), array( 'description' => __( 'Email Subscribers Form', 'email-subscribers' ) ) );
12
+ }
13
+
14
+ public function widget( $args, $instance ) {
15
+
16
+ $title = apply_filters( 'widget_title', $instance['title'] );
17
+
18
+ echo $args['before_widget'];
19
+
20
+ if ( ! empty( $title ) ) {
21
+ echo $args['before_title'] . $title . $args['after_title'];
22
+ }
23
+
24
+ $form_id = isset( $instance['form_id'] ) ? esc_attr( $instance['form_id'] ) : '';
25
+
26
+ $form_data = array();
27
+ if ( ! empty( $form_id ) ) {
28
+
29
+ $form = ES()->forms_db->get_form_by_id( $form_id );
30
+
31
+ $form_data = ES_Forms_Table::get_form_data_from_body( $form );
32
+ }
33
+
34
+
35
+ $data = array();
36
+ $data['form_id'] = 0;
37
+ $data['list'] = '';
38
+ $data['name_visible'] = ( ! empty( $form_data['name_visible'] ) && 'yes' === $form_data['name_visible'] ) ? 'yes' : '';
39
+ $data['name_required'] = ( ! empty( $form_data['name_required'] ) && 'yes' === $form_data['name_required'] ) ? 'yes' : '';
40
+ $data['list_visible'] = ( ! empty( $form_data['list_visible'] ) && 'yes' === $form_data['list_visible'] ) ? 'yes' : '';
41
+ $data['lists'] = ( ! empty( $form_data['lists'] ) ) ? $form_data['lists'] : array();
42
+ $data['desc'] = ( ! empty( $form_data['desc'] ) ) ? $form_data['desc'] : '';
43
+ $data['name_label'] = ( ! empty( $form_data['name_label'] ) ) ? $form_data['name_label'] : '';
44
+ $data['name_place_holder'] = ( ! empty( $form_data['name_place_holder'] ) ) ? $form_data['name_place_holder'] : '';
45
+ $data['email_label'] = ( ! empty( $form_data['email_label'] ) ) ? $form_data['email_label'] : '';
46
+ $data['email_place_holder'] = ( ! empty( $form_data['email_place_holder'] ) ) ? $form_data['email_place_holder'] : '';
47
+ $data['button_label'] = ( ! empty( $form_data['button_label'] ) ) ? $form_data['button_label'] : '';
48
+ $data['form_version'] = ( ! empty( $form_data['form_version'] ) ) ? $form_data['form_version'] : '';
49
+
50
+ ES_Shortcode::render_form( $data );
51
+
52
+ echo $args['after_widget'];
53
+ }
54
+
55
+ public function form( $instance ) {
56
+ $selected_form_id = isset( $instance['form_id'] ) ? esc_attr( $instance['form_id'] ) : '';
57
+ $title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
58
+ ?>
59
+
60
+ <p>
61
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Widget Title:' ); ?></label>
62
+ <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
63
+ </p>
64
+ <p>
65
+ <label for="widget-email-subscribers-2-es_group"><?php _e( 'Forms' ); ?></label>
66
+ <select id="<?php echo $this->get_field_id( 'form_id' ); ?>" name="<?php echo $this->get_field_name( 'form_id' ); ?>" class="widefat" style="width:100%;">
67
+ <?php echo ES_Common::prepare_form_dropdown_options( $selected_form_id, null ); ?>
68
+ </select>
69
+ </p>
70
+ <?php
71
+ }
72
+
73
+ public function update( $new_instance, $old_instance ) {
74
+ $instance = array();
75
+ $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
76
+ $instance['form_id'] = ( ! empty( $new_instance['form_id'] ) ) ? strip_tags( $new_instance['form_id'] ) : '';
77
+
78
+ return $instance;
79
+ }
80
+ }
lite/includes/classes/class-es-forms-table.php ADDED
@@ -0,0 +1,834 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ if ( ! class_exists( 'WP_List_Table' ) ) {
9
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
10
+ }
11
+
12
+ class ES_Forms_Table extends WP_List_Table {
13
+
14
+ /**
15
+ * @since 4.2.1
16
+ * @var string
17
+ *
18
+ */
19
+ public static $option_per_page = 'es_forms_per_page';
20
+
21
+ /**
22
+ * ES_DB_Forms object
23
+ *
24
+ * @since 4.3.1
25
+ * @var $db
26
+ *
27
+ */
28
+ protected $db;
29
+
30
+ /**
31
+ * ES_Forms_Table constructor.
32
+ *
33
+ * @since 4.0
34
+ */
35
+ public function __construct() {
36
+
37
+ parent::__construct( array(
38
+ 'singular' => __( 'Forms', 'email-subscribers' ), //singular name of the listed records
39
+ 'plural' => __( 'Forms', 'email-subscribers' ), //plural name of the listed records
40
+ 'ajax' => false, //does this table support ajax?,
41
+ 'screen' => 'es_forms'
42
+ ) );
43
+
44
+ $this->db = new ES_DB_Forms();
45
+ }
46
+
47
+ /**
48
+ * Add Screen Option
49
+ *
50
+ * @since 4.2.1
51
+ */
52
+ public static function screen_options() {
53
+
54
+ $option = 'per_page';
55
+ $args = array(
56
+ 'label' => __( 'Number of forms per page', 'email-subscribers' ),
57
+ 'default' => 20,
58
+ 'option' => self::$option_per_page
59
+ );
60
+
61
+ add_screen_option( $option, $args );
62
+ }
63
+
64
+
65
+ /**
66
+ * Render Forms list view
67
+ *
68
+ * @since 4.0
69
+ */
70
+ public function render() {
71
+
72
+ $action = ig_es_get_request_data( 'action' );
73
+ ?>
74
+ <div class="wrap">
75
+ <?php if ( 'new' === $action ) {
76
+ $this->es_new_form_callback();
77
+ } elseif ( 'edit' === $action ) {
78
+ $form = ig_es_get_request_data( 'form' );
79
+ echo $this->edit_form( absint( $form ) );
80
+ } else { ?>
81
+ <h1 class="wp-heading-inline"><?php _e( 'Forms', 'email-subscribers' ) ?><a href="admin.php?page=es_forms&action=new" class="page-title-action"> <?php _e( 'Add New', 'email-subscribers' ) ?></a></h1>
82
+ <?php Email_Subscribers_Admin::es_feedback(); ?>
83
+ <div id="poststuff">
84
+ <div id="post-body" class="metabox-holder column-1">
85
+ <div id="post-body-content">
86
+ <div class="meta-box-sortables ui-sortable">
87
+ <form method="post">
88
+ <?php
89
+ $this->prepare_items();
90
+ $this->display(); ?>
91
+ </form>
92
+ </div>
93
+
94
+ </div>
95
+ </div>
96
+ <br class="clear">
97
+ </div>
98
+ </div>
99
+ <?php }
100
+ }
101
+
102
+ public function validate_data( $data ) {
103
+
104
+ $nonce = $data['nonce'];
105
+ $form_name = $data['name'];
106
+ $lists = $data['lists'];
107
+
108
+ $status = 'error';
109
+ $error = false;
110
+ $message = '';
111
+ if ( ! wp_verify_nonce( $nonce, 'es_form' ) ) {
112
+ $message = __( 'You do not have permission to edit this form.', 'email-subscribers' );
113
+ $error = true;
114
+ } elseif ( empty( $form_name ) ) {
115
+ $message = __( 'Please add form name.', 'email-subscribers' );
116
+ $error = true;
117
+ }
118
+
119
+ if ( empty( $lists ) ) {
120
+ $message = __( 'Please select list(s) in which contact will be subscribed.', 'email-subscribers' );
121
+ $error = true;
122
+ }
123
+
124
+ if ( ! $error ) {
125
+ $status = 'success';
126
+ }
127
+
128
+ $response = array(
129
+ 'status' => $status,
130
+ 'message' => $message
131
+ );
132
+
133
+ return $response;
134
+
135
+ }
136
+
137
+ public function es_new_form_callback() {
138
+
139
+ $submitted = ig_es_get_request_data( 'submitted' );
140
+
141
+ if ( 'submitted' === $submitted ) {
142
+
143
+ $nonce = ig_es_get_request_data( '_wpnonce' );
144
+ $form_data = ig_es_get_request_data( 'form_data' );
145
+ $lists = ig_es_get_request_data( 'lists' );
146
+
147
+ $form_data['lists'] = $lists;
148
+
149
+ $validate_data = array(
150
+ 'nonce' => $nonce,
151
+ 'name' => ! empty( $form_data['name'] ) ? sanitize_text_field( $form_data['name'] ) : '',
152
+ 'lists' => ! empty( $form_data['lists'] ) ? $form_data['lists'] : array()
153
+ );
154
+
155
+ $response = $this->validate_data( $validate_data );
156
+
157
+ if ( 'error' === $response['status'] ) {
158
+ $message = $response['message'];
159
+ ES_Common::show_message( $message, 'error' );
160
+ $this->prepare_list_form( null, $form_data );
161
+
162
+ return;
163
+ }
164
+
165
+ $this->save_form( null, $form_data );
166
+ $message = __( 'Form has been added successfully!', 'email-subscribers' );
167
+ ES_Common::show_message( $message, 'success' );
168
+ }
169
+
170
+ $this->prepare_list_form();
171
+ }
172
+
173
+
174
+ public function edit_form( $id ) {
175
+ global $wpdb;
176
+
177
+ if ( $id ) {
178
+ $form_data = array();
179
+
180
+ $data = $wpdb->get_results( "SELECT * FROM " . IG_FORMS_TABLE . " WHERE id = $id", ARRAY_A );
181
+
182
+ if ( count( $data ) > 0 ) {
183
+
184
+ $submitted = ig_es_get_request_data( 'submitted' );
185
+
186
+ if ( 'submitted' === $submitted ) {
187
+
188
+ $nonce = ig_es_get_request_data( '_wpnonce' );
189
+ $form_data = ig_es_get_request_data( 'form_data' );
190
+ $lists = ig_es_get_request_data( 'lists' );
191
+
192
+ $form_data['lists'] = $lists;
193
+
194
+ $validate_data = array(
195
+ 'nonce' => $nonce,
196
+ 'name' => $form_data['name'],
197
+ 'lists' => $form_data['lists']
198
+ );
199
+
200
+ $response = $this->validate_data( $validate_data );
201
+
202
+ if ( 'error' === $response['status'] ) {
203
+ $message = $response['message'];
204
+ ES_Common::show_message( $message, 'error' );
205
+ $this->prepare_list_form( $id, $form_data );
206
+
207
+ return;
208
+ }
209
+
210
+ $this->save_form( $id, $form_data );
211
+ $message = __( 'Form has been updated successfully!', 'email-subscribers' );
212
+ ES_Common::show_message( $message, 'success' );
213
+ } else {
214
+
215
+ $data = $data[0];
216
+ $id = $data['id'];
217
+ $form_data = self::get_form_data_from_body( $data );
218
+ }
219
+ } else {
220
+ $message = __( 'Sorry, form not found', 'email-subscribers' );
221
+ ES_Common::show_message( $message, 'error' );
222
+ }
223
+
224
+ $this->prepare_list_form( $id, $form_data );
225
+ }
226
+ }
227
+
228
+ public function prepare_list_form( $id = 0, $data = array() ) {
229
+
230
+ $is_new = empty( $id ) ? 1 : 0;
231
+
232
+ $action = 'new';
233
+ if ( ! $is_new ) {
234
+ $action = 'edit';
235
+ }
236
+
237
+ $form_data['name'] = ! empty( $data['name'] ) ? sanitize_text_field( $data['name'] ) : '';
238
+ $form_data['name_visible'] = ! empty( $data['name_visible'] ) ? sanitize_text_field( $data['name_visible'] ) : 'no';
239
+ $form_data['name_required'] = ! empty( $data['name_required'] ) ? sanitize_text_field( $data['name_required'] ) : 'no';
240
+ $form_data['name_label'] = ! empty( $data['name_label'] ) ? sanitize_text_field( $data['name_label'] ) : '';
241
+ $form_data['name_place_holder'] = ! empty( $data['name_place_holder'] ) ? sanitize_text_field( $data['name_place_holder'] ) : '';
242
+ $form_data['email_label'] = ! empty( $data['email_label'] ) ? sanitize_text_field( $data['email_label'] ) : '';
243
+ $form_data['email_place_holder'] = ! empty( $data['email_place_holder'] ) ? sanitize_text_field( $data['email_place_holder'] ) : '';
244
+ $form_data['button_label'] = ! empty( $data['button_label'] ) ? sanitize_text_field( $data['button_label'] ) : __( 'Subscribe', 'email-subscribers' );
245
+ $form_data['list_visible'] = ! empty( $data['list_visible'] ) ? $data['list_visible'] : 'no';
246
+ $form_data['lists'] = ! empty( $data['lists'] ) ? $data['lists'] : array();
247
+ $form_data['af_id'] = ! empty( $data['af_id'] ) ? $data['af_id'] : 0;
248
+ $form_data['desc'] = ! empty( $data['desc'] ) ? sanitize_text_field( $data['desc'] ) : '';
249
+
250
+ $lists = ES()->lists_db->get_list_id_name_map();
251
+ $nonce = wp_create_nonce( 'es_form' );
252
+
253
+ ?>
254
+
255
+ <div class="wrap">
256
+ <h1 class="wp-heading-inline">
257
+ <?php
258
+ if ( $is_new ) {
259
+ _e( 'New Form', 'email-subscribers' );
260
+ } else {
261
+ _e( 'Edit Form', 'email-subscribers' );
262
+ }
263
+
264
+ ?>
265
+ </h1>
266
+
267
+ <?php Email_Subscribers_Admin::es_feedback(); ?>
268
+
269
+ <div id="poststuff">
270
+ <div id="post-body" class="metabox-holder column-1">
271
+ <div id="post-body-content">
272
+ <div class="meta-box-sortables ui-sortable">
273
+ <form method="post" action="admin.php?page=es_forms&action=<?php echo $action; ?>&form=<?php echo $id; ?>&_wpnonce=<?php echo $nonce; ?>">
274
+ <table class="form-table">
275
+ <tbody>
276
+ <tr>
277
+ <th scope="row">
278
+ <label for="tag-link"><?php echo __( 'Form Name', 'email-subscribers' ); ?></label>
279
+ </th>
280
+ <td>
281
+ <input type="text" name="form_data[name]" id="ig_es_title" value="<?php echo stripslashes( $form_data['name'] ); ?>" size="30" maxlength="100"/>
282
+ </td>
283
+ </tr>
284
+ <tr>
285
+ <th scope="row">
286
+ <label for="tag-link"><?php echo __( 'Description', 'email-subscribers' ); ?></label>
287
+ </th>
288
+ <td>
289
+ <input type="text" name="form_data[desc]" id="ig_es_title" value="<?php echo stripslashes( $form_data['desc'] ); ?>" size="30" maxlength="100"/>
290
+ </td>
291
+ </tr>
292
+ <tr>
293
+ <th scope="row">
294
+ <label for="tag-link"><?php echo __( 'Form Fields', 'email-subscribers' ); ?></label>
295
+ </th>
296
+ <td>
297
+ <table class="">
298
+ <tr class="form-field">
299
+ <td><b><?php _e( 'Field', 'email-subscribers' ); ?></b></td>
300
+ <td><b><?php _e( 'Show?', 'email-subscribers' ); ?></b></td>
301
+ <td><b><?php _e( 'Required?', 'email-subscribers' ); ?></b></td>
302
+ <td><b><?php _e( 'Label', 'email-subscribers' ); ?></b></td>
303
+ <td><b><?php _e( 'Place Holder', 'email-subscribers' ); ?></b></td>
304
+ </tr>
305
+ <tr class="form-field">
306
+ <td><?php _e( 'Email', 'email-subscribers' ); ?></td>
307
+ <td><input type="checkbox" class="" name="form_data[email_visible]" value="yes" disabled="disabled" checked="checked"></td>
308
+ <td><input type="checkbox" class="" name="form_data[email_required]" value="yes" disabled="disabled" checked="checked"></td>
309
+ <td><input type="text" class="" name="form_data[email_label]" value="<?php echo $form_data['email_label']; ?>"></td>
310
+ <td><input type="text" class="" name="form_data[email_place_holder]" value="<?php echo $form_data['email_place_holder']; ?>"></td>
311
+ </tr>
312
+ <tr class="form-field">
313
+ <td><?php _e( 'Name', 'email-subscribers' ); ?></td>
314
+ <td><input type="checkbox" class="es_visible" name="form_data[name_visible]" value="yes" <?php if ( $form_data['name_visible'] === 'yes' ) {
315
+ echo 'checked="checked"';
316
+ } ?> /></td>
317
+ <td><input type="checkbox" class="es_required" name="form_data[name_required]" value="yes" <?php if ( $form_data['name_required'] === 'yes' ) {
318
+ echo 'checked=checked';
319
+ } ?>></td>
320
+ <td><input type="text" class="es_name_label" name="form_data[name_label]" value="<?php echo $form_data['name_label']; ?>" <?php if ( $form_data['name_required'] === 'yes' ) {
321
+ echo 'disabled=disabled';
322
+ } ?> ></td>
323
+ <td><input type="text" class="es_name_label" name="form_data[name_place_holder]" value="<?php echo $form_data['name_place_holder']; ?>" <?php if ( $form_data['name_required'] === 'yes' ) {
324
+ echo 'disabled=disabled';
325
+ } ?> ></td>
326
+ </tr>
327
+ <tr class="form-field">
328
+ <td><?php _e( 'Button', 'email-subscribers' ); ?></td>
329
+ <td><input type="checkbox" class="" name="form_data[button_visible]" value="yes" disabled="disabled" checked="checked"></td>
330
+ <td><input type="checkbox" class="" name="form_data[button_required]" value="yes" disabled="disabled" checked="checked"></td>
331
+ <td><input type="text" class="" name="form_data[button_label]" value="<?php echo $form_data['button_label']; ?>"></td>
332
+ </tr>
333
+ </table>
334
+ </td>
335
+ </tr>
336
+
337
+ <tr>
338
+ <th scope="row">
339
+ <label for="tag-link"><?php echo __( 'Lists', 'email-subscribers' ); ?></label>
340
+ <p class="helper"> <?php _e( 'Contacts will be added into selected list(s)', 'email-subscribers' ); ?></p>
341
+ </th>
342
+ <td>
343
+ <?php
344
+
345
+ if ( count( $lists ) > 0 ) {
346
+
347
+ echo ES_Shortcode::prepare_lists_checkboxes( $lists, array_keys( $lists ), 3, (array) $form_data['lists'] );
348
+
349
+ } else {
350
+ $create_list_link = admin_url( 'admin.php?page=es_lists&action=new' );
351
+ ?>
352
+ <span><?php _e( sprintf( 'List not found. Please <a href="%s">create your first list</a>.', $create_list_link ) ); ?></span>
353
+ <?php } ?>
354
+ </td>
355
+ </tr>
356
+ <tr>
357
+ <th scope="row">
358
+ <label for="tag-link"><?php echo __( 'Allow contact to choose list(s)', 'email-subscribers' ); ?></label>
359
+ <p class="helper"> <?php _e( 'Allow contacts to choose list(s) in which they want to subscribe.', 'email-subscribers' ); ?></p>
360
+ </th>
361
+ <td>
362
+ <input type="radio" name="form_data[list_visible]" value="yes" <?php if ( $form_data['list_visible'] === 'yes' ) {
363
+ echo 'checked="checked"';
364
+ } ?> /><?php _e( 'Yes', 'email-subscribers' ); ?>
365
+
366
+ <input type="radio" name="form_data[list_visible]" value="no" <?php if ( $form_data['list_visible'] === 'no' ) {
367
+ echo 'checked="checked"';
368
+ } ?> /> <?php _e( 'No', 'email-subscribers' ); ?>
369
+ </td>
370
+
371
+
372
+ </tr>
373
+
374
+ </tbody>
375
+ </table>
376
+ <input type="hidden" name="form_data[af_id]" value="<?php echo $form_data['af_id']; ?>"/>
377
+ <input type="hidden" name="submitted" value="submitted"/>
378
+ <?php if ( count( $lists ) > 0 ) { ?>
379
+ <div class="row-blog"><?php submit_button(); ?></div>
380
+ <?php } else {
381
+ $lists_page_url = admin_url( 'admin.php?page=es_lists' );
382
+ $message = __( sprintf( 'List(s) not found. Please create a first list from <a href="%s">here</a>', $lists_page_url ), 'email-subscribers' );
383
+ $status = 'error';
384
+ ES_Common::show_message( $message, $status );
385
+ }
386
+ $url = 'https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=es_form_captcha&utm_campaign=es_upsale';
387
+ ?>
388
+ <div style=" background-image: linear-gradient(-100deg, rgba(250, 247, 133, 0.4), rgba(250, 247, 133, 0.8) 95%, rgba(250, 247, 133, 0.2)); padding: 10px; width: 35%; border-radius: 1em 0 1em 0; "><?php echo sprintf( __( 'Secure your form and avoid spam signups with Email Subscribers Starter Plan <a target="_blank" style="font-weight: bold; cursor:pointer; text-decoration:none" href="%s">Get started</a>',
389
+ 'email-subscribers' ), $url ) ?></div>
390
+ </form>
391
+ </div>
392
+ </div>
393
+ </div>
394
+ <br class="clear">
395
+ </div>
396
+ </div>
397
+
398
+ <?php
399
+
400
+ }
401
+
402
+ public function save_form( $id, $data ) {
403
+
404
+ global $wpdb;
405
+
406
+ $form_data = self::prepare_form_data( $data );
407
+
408
+ if ( ! empty( $id ) ) {
409
+ $form_data['updated_at'] = ig_get_current_date_time();
410
+
411
+ // We don't want to change the created_at date for update
412
+ unset( $form_data['created_at'] );
413
+ $return = $wpdb->update( IG_FORMS_TABLE, $form_data, array( 'id' => $id ) );
414
+ } else {
415
+ $return = $wpdb->insert( IG_FORMS_TABLE, $form_data );
416
+ }
417
+
418
+ return $return;
419
+ }
420
+
421
+ public static function prepare_form_data( $data ) {
422
+
423
+ $form_data = array();
424
+ $name = ! empty( $data['name'] ) ? sanitize_text_field( $data['name'] ) : '';
425
+ $desc = ! empty( $data['desc'] ) ? sanitize_text_field( $data['desc'] ) : '';
426
+ $email_label = ! empty( $data['email_label'] ) ? sanitize_text_field( $data['email_label'] ) : '';
427
+ $email_place_holder = ! empty( $data['email_place_holder'] ) ? sanitize_text_field( $data['email_place_holder'] ) : '';
428
+ $name_label = ! empty( $data['name_label'] ) ? sanitize_text_field( $data['name_label'] ) : '';
429
+ $name_place_holder = ! empty( $data['name_place_holder'] ) ? sanitize_text_field( $data['name_place_holder'] ) : '';
430
+ $button_label = ! empty( $data['button_label'] ) ? sanitize_text_field( $data['button_label'] ) : '';
431
+ $name_visible = ( ! empty( $data['name_visible'] ) && $data['name_visible'] === 'yes' ) ? true : false;
432
+ $name_required = ( ! empty( $data['name_required'] ) && $data['name_required'] === 'yes' ) ? true : false;
433
+ $list_visible = ( ! empty( $data['list_visible'] ) && $data['list_visible'] === 'yes' ) ? true : false;
434
+ $list_requried = true;
435
+ $list_ids = ! empty( $data['lists'] ) ? $data['lists'] : array();
436
+ $af_id = ! empty( $data['af_id'] ) ? $data['af_id'] : 0;
437
+
438
+ $body = array(
439
+ array(
440
+ 'type' => 'text',
441
+ 'name' => 'Name',
442
+ 'id' => 'name',
443
+ 'params' => array(
444
+ 'label' => $name_label,
445
+ 'place_holder' => $name_place_holder,
446
+ 'show' => $name_visible,
447
+ 'required' => $name_required
448
+ ),
449
+
450
+ 'position' => 1
451
+ ),
452
+
453
+ array(
454
+ 'type' => 'text',
455
+ 'name' => 'Email',
456
+ 'id' => 'email',
457
+ 'params' => array(
458
+ 'label' => $email_label,
459
+ 'place_holder' => $email_place_holder,
460
+ 'show' => true,
461
+ 'required' => true
462
+ ),
463
+
464
+ 'position' => 2
465
+ ),
466
+
467
+ array(
468
+ 'type' => 'checkbox',
469
+ 'name' => 'Lists',
470
+ 'id' => 'lists',
471
+ 'params' => array(
472
+ 'label' => 'Lists',
473
+ 'show' => $list_visible,
474
+ 'required' => $list_requried,
475
+ 'values' => $list_ids
476
+ ),
477
+
478
+ 'position' => 3
479
+ ),
480
+
481
+ array(
482
+ 'type' => 'submit',
483
+ 'name' => 'submit',
484
+ 'id' => 'submit',
485
+ 'params' => array(
486
+ 'label' => $button_label,
487
+ 'show' => true,
488
+ 'required' => true
489
+ ),
490
+
491
+ 'position' => 4
492
+ ),
493
+
494
+ );
495
+
496
+ $settings = array(
497
+ 'lists' => $list_ids,
498
+ 'desc' => $desc,
499
+ 'form_version' => ES()->forms_db->version
500
+ );
501
+
502
+ $form_data['name'] = $name;
503
+ $form_data['body'] = maybe_serialize( $body );
504
+ $form_data['settings'] = maybe_serialize( $settings );
505
+ $form_data['styles'] = null;
506
+ $form_data['created_at'] = ig_get_current_date_time();
507
+ $form_data['updated_at'] = null;
508
+ $form_data['deleted_at'] = null;
509
+ $form_data['af_id'] = $af_id;
510
+
511
+ return $form_data;
512
+ }
513
+
514
+ public static function get_form_data_from_body( $data ) {
515
+
516
+ $name = ! empty( $data['name'] ) ? $data['name'] : '';
517
+ $id = ! empty( $data['id'] ) ? $data['id'] : '';
518
+ $af_id = ! empty( $data['af_id'] ) ? $data['af_id'] : '';
519
+ $body_data = maybe_unserialize( $data['body'] );
520
+ $settings_data = maybe_unserialize( $data['settings'] );
521
+
522
+ $desc = ! empty( $settings_data['desc'] ) ? $settings_data['desc'] : '';
523
+ $form_version = ! empty( $settings_data['form_version'] ) ? $settings_data['form_version'] : '0.1';
524
+
525
+ $form_data = array( 'form_id' => $id, 'name' => $name, 'af_id' => $af_id, 'desc' => $desc, 'form_version' => $form_version );
526
+ foreach ( $body_data as $d ) {
527
+ if ( $d['id'] === 'name' ) {
528
+ $form_data['name_visible'] = ( $d['params']['show'] === true ) ? 'yes' : '';
529
+ $form_data['name_required'] = ( $d['params']['required'] === true ) ? 'yes' : '';
530
+ $form_data['name_label'] = ! empty( $d['params']['label'] ) ? $d['params']['label'] : '';
531
+ $form_data['name_place_holder'] = ! empty( $d['params']['place_holder'] ) ? $d['params']['place_holder'] : '';
532
+ } elseif ( $d['id'] === 'lists' ) {
533
+ $form_data['list_visible'] = ( $d['params']['show'] === true ) ? 'yes' : '';
534
+ $form_data['list_required'] = ( $d['params']['required'] === true ) ? 'yes' : '';
535
+ $form_data['lists'] = ! empty( $d['params']['values'] ) ? $d['params']['values'] : array();
536
+ } elseif ( $d['id'] === 'email' ) {
537
+ $form_data['email_label'] = ! empty( $d['params']['label'] ) ? $d['params']['label'] : '';
538
+ $form_data['email_place_holder'] = ! empty( $d['params']['place_holder'] ) ? $d['params']['place_holder'] : '';
539
+ } elseif ( $d['id'] === 'submit' ) {
540
+ $form_data['button_label'] = ! empty( $d['params']['label'] ) ? $d['params']['label'] : '';
541
+ }
542
+ }
543
+
544
+ return $form_data;
545
+ }
546
+
547
+ /**
548
+ * Retrieve lists data from the database
549
+ *
550
+ * @param int $per_page
551
+ * @param int $page_number
552
+ *
553
+ * @return mixed
554
+ */
555
+ public function get_lists( $per_page = 5, $page_number = 1, $do_count_only = false ) {
556
+
557
+ global $wpdb;
558
+
559
+ $order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
560
+ $order = ig_es_get_request_data( 'order' );
561
+ $search = ig_es_get_request_data( 's' );
562
+
563
+ $forms_table = IG_FORMS_TABLE;
564
+ if ( $do_count_only ) {
565
+ $sql = "SELECT count(*) as total FROM {$forms_table}";
566
+ } else {
567
+ $sql = "SELECT * FROM {$forms_table}";
568
+ }
569
+
570
+ $args = $query = array();
571
+
572
+ $add_where_clause = false;
573
+
574
+ if ( ! empty( $search ) ) {
575
+ $query[] = " name LIKE %s ";
576
+ $args[] = "%" . $wpdb->esc_like( $search ) . "%";
577
+
578
+ $add_where_clause = true;
579
+ }
580
+
581
+ if ( $add_where_clause ) {
582
+ $sql .= " WHERE ";
583
+
584
+ if ( count( $query ) > 0 ) {
585
+ $sql .= implode( " AND ", $query );
586
+ if ( count( $args ) > 0 ) {
587
+ $sql = $wpdb->prepare( $sql, $args );
588
+ }
589
+ }
590
+ }
591
+
592
+ if ( ! $do_count_only ) {
593
+
594
+ $order = ! empty( $order ) ? strtolower( $order ) : 'desc';
595
+ $expected_order_values = array( 'asc', 'desc' );
596
+ if ( ! in_array( $order, $expected_order_values ) ) {
597
+ $order = 'desc';
598
+ }
599
+
600
+ $default_order_by = esc_sql( 'created_at' );
601
+
602
+ $expected_order_by_values = array( 'name', 'created_at' );
603
+
604
+ if ( ! in_array( $order_by, $expected_order_by_values ) ) {
605
+ $order_by_clause = " ORDER BY {$default_order_by} DESC";
606
+ } else {
607
+ $order_by = esc_sql( $order_by );
608
+ $order_by_clause = " ORDER BY {$order_by} {$order}, {$default_order_by} DESC";
609
+ }
610
+
611
+ $sql .= $order_by_clause;
612
+ $sql .= " LIMIT $per_page";
613
+ $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
614
+
615
+ $result = $wpdb->get_results( $sql, 'ARRAY_A' );
616
+ } else {
617
+ $result = $wpdb->get_var( $sql );
618
+ }
619
+
620
+ return $result;
621
+ }
622
+
623
+ /**
624
+ * Returns the count of records in the database.
625
+ *
626
+ * @return null|string
627
+ */
628
+ public function record_count() {
629
+ global $wpdb;
630
+
631
+ $sql = "SELECT COUNT(*) FROM " . IG_FORMS_TABLE;
632
+
633
+ return $wpdb->get_var( $sql );
634
+ }
635
+
636
+ /**
637
+ * Render a column when no column specific method exist.
638
+ *
639
+ * @param array $item
640
+ * @param string $column_name
641
+ *
642
+ * @return mixed
643
+ */
644
+ public function column_default( $item, $column_name ) {
645
+ switch ( $column_name ) {
646
+ // case 'status':
647
+ // return $this->status_label_map( $item[ $column_name ] );
648
+ case 'created_at':
649
+ return ig_es_format_date_time( $item[ $column_name ] );
650
+ break;
651
+ case 'shortcode':
652
+ $shortcode = '[email-subscribers-form id="' . $item['id'] . '"]';
653
+
654
+ return '<code>' . $shortcode . '</code>';
655
+ break;
656
+ default:
657
+ return '';
658
+ }
659
+ }
660
+
661
+ /**
662
+ * Render the bulk edit checkbox
663
+ *
664
+ * @param array $item
665
+ *
666
+ * @return string
667
+ */
668
+ function column_cb( $item ) {
669
+ return sprintf(
670
+ '<input type="checkbox" name="forms[]" value="%s" />', $item['id']
671
+ );
672
+ }
673
+
674
+ /**
675
+ * Method for name column
676
+ *
677
+ * @param array $item an array of DB data
678
+ *
679
+ * @return string
680
+ */
681
+ function column_name( $item ) {
682
+
683
+ $list_nonce = wp_create_nonce( 'es_form' );
684
+
685
+ $title = '<strong>' . stripslashes( $item['name'] ) . '</strong>';
686
+
687
+ $page = ig_es_get_request_data( 'page' );
688
+ $actions = array(
689
+ 'edit' => sprintf( __( '<a href="?page=%s&action=%s&form=%s&_wpnonce=%s">Edit</a>', 'email-subscribers' ), esc_attr( $page ), 'edit', absint( $item['id'] ), $list_nonce ),
690
+ 'delete' => sprintf( __( '<a href="?page=%s&action=%s&form=%s&_wpnonce=%s" onclick="return checkDelete()">Delete</a>', 'email-subscribers' ), esc_attr( $page ), 'delete', absint( $item['id'] ), $list_nonce )
691
+ );
692
+
693
+ return $title . $this->row_actions( $actions );
694
+ }
695
+
696
+
697
+ /**
698
+ * Associative array of columns
699
+ *
700
+ * @return array
701
+ */
702
+ function get_columns() {
703
+ $columns = array(
704
+ 'cb' => '<input type="checkbox" />',
705
+ 'name' => __( 'Name', 'email-subscribers' ),
706
+ 'shortcode' => __( 'Shortcode', 'email-subscribers' ),
707
+ 'created_at' => __( 'Created', 'email-subscribers' )
708
+ );
709
+
710
+ return $columns;
711
+ }
712
+
713
+
714
+ /**
715
+ * Columns to make sortable.
716
+ *
717
+ * @return array
718
+ */
719
+ public function get_sortable_columns() {
720
+ $sortable_columns = array(
721
+ 'name' => array( 'name', true ),
722
+ 'created_at' => array( 'created_at', true ),
723
+ );
724
+
725
+ return $sortable_columns;
726
+ }
727
+
728
+ /**
729
+ * Returns an associative array containing the bulk action
730
+ *
731
+ * @return array
732
+ */
733
+ public function get_bulk_actions() {
734
+ $actions = array(
735
+ 'bulk_delete' => __( 'Delete', 'email-subscribers' )
736
+ );
737
+
738
+ return $actions;
739
+ }
740
+
741
+ public function search_box( $text, $input_id ) { ?>
742
+ <p class="search-box">
743
+ <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
744
+ <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>"/>
745
+ <?php submit_button( __( 'Search Forms', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
746
+ </p>
747
+ <?php }
748
+
749
+ /**
750
+ * Handles data query and filter, sorting, and pagination.
751
+ */
752
+ public function prepare_items() {
753
+
754
+ $this->_column_headers = $this->get_column_info();
755
+
756
+
757
+ /** Process bulk action */
758
+ $this->process_bulk_action();
759
+
760
+ $search_str = ig_es_get_request_data( 's' );
761
+ $this->search_box( $search_str, 'form-search-input' );
762
+
763
+ $per_page = $this->get_items_per_page( self::$option_per_page, 25 );
764
+ $current_page = $this->get_pagenum();
765
+ $total_items = $this->get_lists( 0, 0, true );
766
+
767
+ $this->set_pagination_args( array(
768
+ 'total_items' => $total_items, //WE have to calculate the total number of items
769
+ 'per_page' => $per_page //WE have to determine how many items to show on a page
770
+ ) );
771
+
772
+ $this->items = $this->get_lists( $per_page, $current_page );
773
+ }
774
+
775
+ public function process_bulk_action() {
776
+
777
+ if ( 'delete' === $this->current_action() ) {
778
+
779
+ // In our file that handles the request, verify the nonce.
780
+ $nonce = ig_es_get_request_data( '_wpnonce' );
781
+
782
+ if ( ! wp_verify_nonce( $nonce, 'es_form' ) ) {
783
+ $message = __( 'You do not have permission to delete this form.', 'email-subscribers' );
784
+ ES_Common::show_message( $message, 'error' );
785
+ } else {
786
+
787
+ $form = ig_es_get_request_data( 'form' );
788
+
789
+ $this->db->delete_forms( array( $form ) );
790
+ $message = __( 'Form has been deleted successfully!', 'email-subscribers' );
791
+ ES_Common::show_message( $message, 'success' );
792
+ }
793
+ }
794
+
795
+ $action = ig_es_get_request_data( 'action' );
796
+ $action2 = ig_es_get_request_data( 'action2' );
797
+ // If the delete bulk action is triggered
798
+ if ( ( 'bulk_delete' === $action ) || ( 'bulk_delete' === $action2 ) ) {
799
+
800
+ $forms = ig_es_get_request_data( 'forms' );
801
+
802
+ if ( ! empty( $forms ) > 0 ) {
803
+ $this->db->delete_forms( $forms );
804
+
805
+ $message = __( 'Form(s) have been deleted successfully!', 'email-subscribers' );
806
+ ES_Common::show_message( $message, 'success' );
807
+ } else {
808
+ $message = __( 'Please select form(s) to delete.', 'email-subscribers' );
809
+ ES_Common::show_message( $message, 'error' );
810
+
811
+ return;
812
+ }
813
+ }
814
+ }
815
+
816
+ public function status_label_map( $status ) {
817
+
818
+ $statuses = array(
819
+ 'enable' => __( 'Enable', 'email-subscribers' ),
820
+ 'disable' => __( 'Disable', 'email-subscribers' )
821
+ );
822
+
823
+ if ( ! in_array( $status, array_keys( $statuses ) ) ) {
824
+ return '';
825
+ }
826
+
827
+ return $statuses[ $status ];
828
+ }
829
+
830
+ /** Text displayed when no list data is available */
831
+ public function no_items() {
832
+ _e( 'No Forms avaliable.', 'email-subscribers' );
833
+ }
834
+ }
lite/includes/classes/class-es-handle-post-notification.php ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class ES_Handle_Post_Notification {
4
+
5
+ public $is_wp_5 = false;
6
+
7
+ public $is_rest_request = false;
8
+
9
+ public $do_post_notification_via_wp_5_hook = false;
10
+
11
+ public $do_post_notification_for = 0;
12
+
13
+ public function __construct() {
14
+ global $wp_version;
15
+
16
+ // Action is available after WordPress 2.3.0+
17
+ add_action( 'transition_post_status', array( $this, 'es_post_publish_callback' ), 10, 3 );
18
+
19
+ // Action is available WordPress 5.0+
20
+ add_action( 'rest_after_insert_post', array( $this, 'handle_post_publish' ), 10, 3 );
21
+
22
+ // Filter is available after WordPress 4.7.0+
23
+ add_filter( 'rest_pre_insert_post', array( $this, 'prepare_post_data' ), 10, 2 );
24
+
25
+ if ( version_compare( $wp_version, '5.0.0', '>=' ) ) {
26
+ $this->is_wp_5 = true;
27
+ }
28
+
29
+ add_action( 'ig_es_refresh_post_notification_content', array( $this, 'refresh_post_content' ), 10, 2 );
30
+ }
31
+
32
+ public function prepare_post_data( $prepared_post, $request ) {
33
+ $this->is_rest_request = true;
34
+
35
+ return $prepared_post;
36
+ }
37
+
38
+ public function handle_post_publish( $post, $requst, $insert ) {
39
+ // If it's inserted for the first time????
40
+ // Not able to check whether it'a first time post or nth times
41
+ if ( is_object( $post ) && ( $post instanceof WP_Post ) ) { // Do it for the first time only
42
+
43
+ if ( $this->do_post_notification_via_wp_5_hook ) {
44
+ $post_id = $post->ID;
45
+ if ( $post_id == $this->do_post_notification_for ) {
46
+ $this->queue_post_notifications( $post_id );
47
+ }
48
+ }
49
+ }
50
+
51
+ }
52
+
53
+ public function es_post_publish_callback( $post_status, $original_post_status, $post ) {
54
+
55
+ if ( ( $post_status == 'publish' ) && ( $original_post_status != 'publish' ) ) {
56
+
57
+ if ( is_object( $post ) ) {
58
+
59
+ $post_id = $post->ID;
60
+ if ( ! empty( $post_id ) ) {
61
+
62
+ if ( $this->is_wp_5 && $this->is_rest_request ) {
63
+ $this->do_post_notification_via_wp_5_hook = true;
64
+ $this->do_post_notification_for = $post_id;
65
+ } else {
66
+ $this->queue_post_notifications( $post_id );
67
+ }
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ public function queue_post_notifications( $post_id ) {
74
+
75
+ if ( ! empty( $post_id ) ) {
76
+
77
+ $notifications = ES_DB_Notifications::get_notifications_by_post_id( $post_id );
78
+ if ( count( $notifications ) > 0 ) {
79
+ $existing_contacts = array();
80
+ foreach ( $notifications as $notification ) {
81
+ $template_id = $notification['base_template_id'];
82
+ $template = get_post( $template_id ); // to confirm if template exists in ES->Templates
83
+ if ( is_object( $template ) ) {
84
+ $list_id = $notification['list_ids'];
85
+ $subscribers = ES()->contacts_db->get_active_contacts_by_list_id( $list_id );
86
+
87
+ //schedule
88
+ if ( count( $subscribers ) > 0 ) {
89
+ /*
90
+ * Prepare Subject
91
+ * Prepare Body
92
+ * Add entry into sent_details table
93
+ * Add entry into deliverreport table
94
+ */
95
+
96
+ foreach ( $subscribers as $key => $subscriber ) {
97
+ if ( in_array( $subscriber['id'], $existing_contacts ) ) {
98
+ unset( $subscribers[ $key ] );
99
+ } else {
100
+ $existing_contacts[] = $subscriber['id'];
101
+ }
102
+ }
103
+ /*check again for unique subscribers count
104
+ if unique count it 0 then skip this report
105
+ */
106
+ if ( count( $subscribers ) <= 0 ) {
107
+ continue;
108
+ }
109
+
110
+ $post = get_post( $post_id );
111
+
112
+ if ( is_object( $post ) ) {
113
+ // Prepare subject
114
+ $post_subject = self::prepare_subject( $post, $template );
115
+
116
+ // Prepare body
117
+ $template_content = $template->post_content;
118
+ $post_content = self::prepare_body( $template_content, $post_id, $template_id );
119
+
120
+ $guid = ES_Common::generate_guid( 6 );
121
+
122
+ $data = array(
123
+ 'hash' => $guid,
124
+ 'campaign_id' => $notification['id'],
125
+ 'subject' => $post_subject,
126
+ 'body' => $post_content,
127
+ 'count' => count( $subscribers ),
128
+ 'status' => 'In Queue',
129
+ 'start_at' => '',
130
+ 'finish_at' => '',
131
+ 'created_at' => ig_get_current_date_time(),
132
+ 'updated_at' => ig_get_current_date_time(),
133
+ 'meta' => maybe_serialize( array( 'post_id' => $post_id, 'type' => 'post_notification' ) )
134
+ );
135
+
136
+ // Add entry into mailing queue table
137
+ $insert = ES_DB_Mailing_Queue::add_notification( $data );
138
+ if ( $insert ) {
139
+ // Add entry into sending queue table
140
+ $delivery_data = array();
141
+ $delivery_data['hash'] = $guid;
142
+ $delivery_data['subscribers'] = $subscribers;
143
+ $delivery_data['campaign_id'] = $notification['id'];
144
+ $delivery_data['mailing_queue_id'] = $insert;
145
+ ES_DB_Sending_Queue::do_batch_insert( $delivery_data );
146
+
147
+ }
148
+
149
+ }
150
+ }
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+
157
+ public static function prepare_subject( $post, $template ) {
158
+ //convert post subject here
159
+
160
+ $post_title = $post->post_title;
161
+ $template_title = $template->post_title;
162
+
163
+ $blog_charset = get_option( 'blog_charset' );
164
+
165
+ $post_title = html_entity_decode( $post_title, ENT_QUOTES, $blog_charset );
166
+ $post_subject = str_replace( '{{POSTTITLE}}', $post_title, $template_title );
167
+
168
+ $post_link = get_permalink( $post );
169
+ $post_subject = str_replace( '{{POSTLINK}}', $post_link, $post_subject );
170
+
171
+ return $post_subject;
172
+
173
+ }
174
+
175
+ public static function prepare_body( $es_templ_body, $post_id, $email_template_id ) {
176
+ $post = get_post( $post_id );
177
+ $post_date = $post->post_modified;
178
+ $es_templ_body = str_replace( '{{DATE}}', $post_date, $es_templ_body );
179
+
180
+ $post_title = get_the_title( $post );
181
+ $es_templ_body = str_replace( '{{POSTTITLE}}', $post_title, $es_templ_body );
182
+ $post_link = get_permalink( $post_id );
183
+
184
+ // Size of {{POSTIMAGE}}
185
+ $post_thumbnail = "";
186
+ $post_thumbnail_link = "";
187
+ if ( ( function_exists( 'has_post_thumbnail' ) ) && ( has_post_thumbnail( $post_id ) ) ) {
188
+ $es_post_image_size = get_option( 'ig_es_post_image_size', 'full' );
189
+ switch ( $es_post_image_size ) {
190
+ case 'full':
191
+ $post_thumbnail = get_the_post_thumbnail( $post_id, 'full' );
192
+ break;
193
+ case 'medium':
194
+ $post_thumbnail = get_the_post_thumbnail( $post_id, 'medium' );
195
+ break;
196
+ case 'thumbnail':
197
+ default:
198
+ $post_thumbnail = get_the_post_thumbnail( $post_id, 'thumbnail' );
199
+ break;
200
+ }
201
+ }
202
+
203
+ if ( $post_thumbnail != "" ) {
204
+ $post_thumbnail_link = "<a href='" . $post_link . "' target='_blank'>" . $post_thumbnail . "</a>";
205
+ }
206
+ $es_templ_body = str_replace( '{{POSTIMAGE}}', $post_thumbnail_link, $es_templ_body );
207
+
208
+ // Get post description
209
+ $post_description_length = 50;
210
+ $post_description = $post->post_content;
211
+ $post_description = strip_tags( strip_shortcodes( $post_description ) );
212
+ $words = explode( ' ', $post_description, $post_description_length + 1 );
213
+ if ( count( $words ) > $post_description_length ) {
214
+ array_pop( $words );
215
+ array_push( $words, '...' );
216
+ $post_description = implode( ' ', $words );
217
+ }
218
+ $es_templ_body = str_replace( '{{POSTDESC}}', $post_description, $es_templ_body );
219
+
220
+ // Get post excerpt
221
+ $post_excerpt = get_the_excerpt( $post );
222
+ $es_templ_body = str_replace( '{{POSTEXCERPT}}', $post_excerpt, $es_templ_body );
223
+
224
+ // get post author
225
+ $post_author_id = $post->post_author;
226
+ $post_author = get_the_author_meta( 'display_name', $post_author_id );
227
+ $es_templ_body = str_replace( '{{POSTAUTHOR}}', $post_author, $es_templ_body );
228
+ $es_templ_body = str_replace( '{{POSTLINK-ONLY}}', $post_link, $es_templ_body );
229
+
230
+ if ( $post_link != "" ) {
231
+ $post_link_with_title = "<a href='" . $post_link . "' target='_blank'>" . $post_title . "</a>";
232
+ $es_templ_body = str_replace( '{{POSTLINK-WITHTITLE}}', $post_link_with_title, $es_templ_body );
233
+ $post_link = "<a href='" . $post_link . "' target='_blank'>" . $post_link . "</a>";
234
+ }
235
+ $es_templ_body = str_replace( '{{POSTLINK}}', $post_link, $es_templ_body );
236
+
237
+ // Get full post
238
+ $post_full = $post->post_content;
239
+ $post_full = wpautop( $post_full );
240
+ $es_templ_body = str_replace( '{{POSTFULL}}', $post_full, $es_templ_body );
241
+ // add pre header as post excerpt
242
+ if( !empty($post_excerpt) ){
243
+ $es_templ_body = '<span class="es_preheader" style="display: none !important; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;">'.$post_excerpt.'</span>'.$es_templ_body;
244
+ }
245
+ if($email_template_id > 0){
246
+ $es_templ_body = ES_Common::es_process_template_body( $es_templ_body, $email_template_id );
247
+ }
248
+
249
+ return $es_templ_body;
250
+ }
251
+
252
+ public static function refresh_post_content( $content, $args ) {
253
+ $campaign_id = $args['campaign_id'];
254
+ $post_id = $args['post_id'];
255
+ $post = get_post( $post_id );
256
+ $template_id = ES()->campaigns_db->get_template_id_by_campaign( $campaign_id );
257
+ $template = get_post( $template_id );
258
+ $template_content = $template->post_content;
259
+ $content['subject'] = self::prepare_subject( $post, $template );
260
+ $content['body'] = self::prepare_body( $template_content, $post_id, $template_id );
261
+ return $content;
262
+ }
263
+
264
+ }
265
+
lite/includes/classes/class-es-handle-subscription.php ADDED
@@ -0,0 +1,443 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
9
+ /**
10
+ * Handle subscription
11
+ *
12
+ * Class ES_Handle_Subscription
13
+ *
14
+ * @since 4.0.0
15
+ */
16
+ class ES_Handle_Subscription {
17
+ /**
18
+ * @since 4.0.0
19
+ * @var
20
+ *
21
+ */
22
+ public $email;
23
+ /**
24
+ * @since 4.0.0
25
+ * @var
26
+ *
27
+ */
28
+ public $name;
29
+ /**
30
+ * @since 4.0.0
31
+ * @var
32
+ *
33
+ */
34
+ public $first_name;
35
+ /**
36
+ * @since 4.0.0
37
+ * @var
38
+ *
39
+ */
40
+ public $last_name;
41
+ /**
42
+ * @since 4.0.0
43
+ * @var
44
+ *
45
+ */
46
+ public $es_optin_type;
47
+ /**
48
+ * @since 4.0.0
49
+ * @var
50
+ *
51
+ */
52
+ public $list_ids;
53
+ /**
54
+ * @since 4.0.0
55
+ * @var
56
+ *
57
+ */
58
+ public $es_nonce;
59
+ /**
60
+ * @since 4.0.0
61
+ * @var
62
+ *
63
+ */
64
+ public $status;
65
+ /**
66
+ * @since 4.0.0
67
+ * @var
68
+ *
69
+ */
70
+ public $is_double_optin = false;
71
+ /**
72
+ * @since 4.0.0
73
+ * @var
74
+ *
75
+ */
76
+ public $guid;
77
+ /**
78
+ * @since 4.0.0
79
+ * @var
80
+ *
81
+ */
82
+ public $db_id;
83
+ /**
84
+ * @since 4.0.0
85
+ * @var
86
+ *
87
+ */
88
+ public $form_id;
89
+ /**
90
+ * @since 4.0.0
91
+ * @var
92
+ *
93
+ */
94
+ private $from_rainmaker = false;
95
+
96
+ /**
97
+ * ES_Handle_Subscription constructor.
98
+ *
99
+ * @param bool $from_rainmaker
100
+ *
101
+ * @since 4.0.0
102
+ */
103
+ public function __construct( $from_rainmaker = false ) {
104
+ if ( defined( 'DOING_AJAX' ) && ( true === DOING_AJAX ) ) {
105
+ add_action( 'wp_ajax_es_add_subscriber', array( $this, 'process_request' ), 10 );
106
+ add_action( 'wp_ajax_nopriv_es_add_subscriber', array( $this, 'process_request' ), 10 );
107
+ }
108
+
109
+ $this->from_rainmaker = $from_rainmaker;
110
+ }
111
+
112
+ /**
113
+ * Process request
114
+ *
115
+ * @since 4.0.0
116
+ */
117
+ public function process_request() {
118
+
119
+ $response = array( 'status' => 'ERROR', 'message' => '' );
120
+
121
+ $es = ig_es_get_post_data( 'es' );
122
+ $es_subscribe = ig_es_get_post_data( 'esfpx_es-subscribe' );
123
+
124
+ if ( 'subscribe' === $es && ! empty( $es_subscribe ) ) {
125
+
126
+ $form_data = ig_es_get_post_data();
127
+ $validate_response = $this->validate_data( $form_data );
128
+ if ( $validate_response['status'] === 'ERROR' ) {
129
+
130
+ // We want to pretend as "SUCCESS" for blocked emails.
131
+ // So, we are setting as "SUCCESS" even if this email is blocked
132
+ if ( $validate_response['message'] === 'es_email_address_blocked' ) {
133
+ $validate_response['status'] = 'SUCCESS';
134
+ $validate_response['message'] = 'es_optin_success_message';
135
+ }
136
+
137
+ $this->do_response( $validate_response );
138
+ exit;
139
+ }
140
+
141
+ $email = ! empty( $form_data['esfpx_email'] ) ? sanitize_email( $form_data['esfpx_email'] ) : '';
142
+ $name = ! empty( $form_data['esfpx_name'] ) ? sanitize_text_field( $form_data['esfpx_name'] ) : '';
143
+
144
+ $first_name = $last_name = '';
145
+ if ( ! empty( $name ) ) {
146
+ // Get First Name and Last Name from Name
147
+ $name_parts = ES_Common::prepare_first_name_last_name( $name );
148
+ $first_name = $name_parts['first_name'];
149
+ $last_name = $name_parts['last_name'];
150
+ } else {
151
+ $first_name = ES_Common::get_name_from_email( $email );
152
+ }
153
+
154
+ $this->name = $first_name;
155
+ $this->first_name = $first_name;
156
+ $this->last_name = $last_name;
157
+ $this->email = $email;
158
+ $this->list_ids = isset( $form_data['esfpx_lists'] ) ? $form_data['esfpx_lists'] : array();
159
+ $this->es_nonce = isset( $form_data['esfpx_es-subscribe'] ) ? trim( $form_data['esfpx_es-subscribe'] ) : '';
160
+ $this->form_id = isset( $form_data['esfpx_form_id'] ) ? trim( $form_data['esfpx_form_id'] ) : 0;
161
+ $this->es_optin_type = get_option( 'ig_es_optin_type' );
162
+ $this->guid = ES_Common::generate_guid();
163
+
164
+ if ( in_array( $this->es_optin_type, array( 'double_opt_in', 'double_optin' ) ) ) { // Backward Compatibility
165
+ $this->is_double_optin = true;
166
+ $this->status = "unconfirmed";
167
+ } else {
168
+ $this->status = "subscribed";
169
+ }
170
+
171
+ /**
172
+ * Check if subscribers exists?
173
+ * - If yes, get id and save lists into ig_lists_contacts table
174
+ * - If not, create contact and then save list
175
+ */
176
+
177
+ $contact_id = ES()->contacts_db->get_contact_id_by_email( $this->email );
178
+ if ( ! $contact_id ) {
179
+ $data = array();
180
+ $data['first_name'] = $this->first_name;
181
+ $data['last_name'] = $this->last_name;
182
+ $data['source'] = 'form';
183
+ $data['form_id'] = $this->form_id;
184
+ $data['email'] = $this->email;
185
+ $data['hash'] = $this->guid;
186
+ $data['status'] = 'verified';
187
+ $data['hash'] = $this->guid;
188
+ $data['created_at'] = ig_get_current_date_time();
189
+ $data['updated_at'] = null;
190
+ $data['meta'] = null;
191
+
192
+ $data = apply_filters( 'ig_es_add_subscriber_data', $data );
193
+ if ( 'ERROR' === $data['status'] ) {
194
+ $this->do_response( $validate_response );
195
+ exit;
196
+ }
197
+
198
+ $contact_id = ES()->contacts_db->insert( $data );
199
+
200
+ //do_action( 'ig_es_contact_added', $data);
201
+
202
+ }
203
+
204
+ if ( count( $this->list_ids ) > 0 ) {
205
+ $contact_lists = ES_DB_Lists_Contacts::get_list_ids_by_contact( $contact_id, 'subscribed' );
206
+ if ( $contact_lists == $this->list_ids ) {
207
+ $response['message'] = 'es_email_exists_notice';
208
+ $this->do_response( $response );
209
+ exit;
210
+ }
211
+ $optin_type = $this->is_double_optin ? IG_DOUBLE_OPTIN : IG_SINGLE_OPTIN;
212
+ $list_contact_data = array(
213
+ 'list_id' => $this->list_ids,
214
+ 'contact_id' => $contact_id,
215
+ 'status' => $this->status,
216
+ 'subscribed_at' => ( $this->status === 'subscribed' ) ? ig_get_current_date_time() : '',
217
+ 'optin_type' => $optin_type,
218
+ 'subscribed_ip' => ig_es_get_ip()
219
+ );
220
+ ES_DB_Lists_Contacts::delete_list_contacts( $contact_id, $this->list_ids );
221
+ ES_DB_Lists_Contacts::add_lists_contacts( $list_contact_data );
222
+
223
+ if ( $contact_id ) {
224
+
225
+ do_action( 'ig_es_contact_subscribe', $contact_id, $this->list_ids );
226
+
227
+ $this->db_id = $contact_id;
228
+
229
+ // Get comma(,) separated lists name based on ids.
230
+ $list_name = ES_Common::prepare_list_name_by_ids( $this->list_ids );
231
+
232
+ $merge_tags = array(
233
+ 'email' => $this->email,
234
+ 'contact_id' => $contact_id,
235
+ 'name' => ES_Common::prepare_name_from_first_name_last_name( $this->first_name, $this->last_name ),
236
+ 'first_name' => $this->first_name,
237
+ 'last_name' => $this->last_name,
238
+ 'guid' => $this->guid,
239
+ 'list_name' => $list_name
240
+ );
241
+
242
+ if ( $this->is_double_optin ) {
243
+ $response = ES()->mailer->send_double_optin_email( $this->email, $merge_tags );
244
+ $response['message'] = 'es_optin_success_message';
245
+ } else {
246
+ // Send Welcome Email
247
+ ES()->mailer->send_welcome_email( $this->email, $merge_tags );
248
+
249
+ // Send Notifications to admins
250
+ ES()->mailer->send_add_new_contact_notification_to_admins( $merge_tags );
251
+
252
+ $response['message'] = 'es_optin_success_message';
253
+ }
254
+
255
+ $response['status'] = 'SUCCESS';
256
+ } else {
257
+
258
+ $response['message'] = 'es_db_error_notice';
259
+ }
260
+ } else {
261
+ $response['message'] = 'es_no_list_selected';
262
+ $this->do_response( $response );
263
+ exit;
264
+ }
265
+ } else {
266
+ $response['message'] = 'es_permission_denied_notice';
267
+ }
268
+
269
+ $this->do_response( $response );
270
+ exit;
271
+ }
272
+
273
+ /**
274
+ * Send Response
275
+ *
276
+ * @param $response
277
+ *
278
+ * @since 4.0.0
279
+ */
280
+ public function do_response( $response ) {
281
+
282
+ $message = isset( $response['message'] ) ? $response['message'] : '';
283
+ $response['message_text'] = '';
284
+ if ( ! empty( $message ) ) {
285
+ $response['message_text'] = $this->get_messages( $message );
286
+ }
287
+
288
+ echo json_encode( $response );
289
+ exit;
290
+
291
+ }
292
+
293
+ /**
294
+ * Validate subscribers data
295
+ *
296
+ * @param $data
297
+ *
298
+ * @return array|mixed|void
299
+ *
300
+ * @since 4.0.0
301
+ */
302
+ public function validate_data( $data ) {
303
+
304
+ $es_response = array( 'status' => 'ERROR', 'message' => '' );
305
+
306
+ if ( ! $this->from_rainmaker ) {
307
+
308
+ // Honeypot validation
309
+ $hp_key = "esfpx_es_hp_" . wp_create_nonce( 'es_hp' );
310
+ if ( ! isset( $data[ $hp_key ] ) || ! empty( $data[ $hp_key ] ) ) {
311
+ $es_response['message'] = 'es_unexpected_error_notice';
312
+
313
+ return $es_response;
314
+ }
315
+ }
316
+
317
+ $name = isset( $data['esfpx_name'] ) ? $data['esfpx_name'] : '';
318
+ if ( strlen( $name ) > 50 ) {
319
+ $es_response['message'] = 'es_invalid_name_notice';
320
+
321
+ return $es_response;
322
+ }
323
+
324
+ $email = isset( $data['esfpx_email'] ) ? $data['esfpx_email'] : '';
325
+
326
+ if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
327
+ $es_response['message'] = 'es_invalid_email_notice';
328
+
329
+ return $es_response;
330
+ }
331
+
332
+ $is_domain_blocked = $this->is_domain_blocked( $email );
333
+
334
+ // Store it blocked emails
335
+ if ( $is_domain_blocked ) {
336
+ $data = array(
337
+ 'email' => $email,
338
+ 'ip' => ig_es_get_ip()
339
+ );
340
+
341
+ ES()->blocked_emails_db->insert( $data );
342
+
343
+ $es_response['status'] = 'ERROR';
344
+ $es_response['message'] = 'es_email_address_blocked';
345
+
346
+ return $es_response;
347
+ }
348
+
349
+ $data = apply_filters( 'ig_es_validate_subscribers_data', $data );
350
+
351
+ if ( ! empty( $data['status'] ) && 'ERROR' === $data['status'] ) {
352
+ $es_response = $data;
353
+
354
+ return $es_response;
355
+ }
356
+
357
+ $timeout = ES_Subscription_Throttling::throttle();
358
+ if ( $timeout > 0 ) {
359
+ $es_response['message'] = 'es_rate_limit_notice';
360
+
361
+ return $es_response;
362
+ }
363
+
364
+ $es_response['status'] = 'SUCCESS';
365
+
366
+ return $es_response;
367
+ }
368
+
369
+ /**
370
+ * @param $email
371
+ *
372
+ * @return bool
373
+ *
374
+ * @since 4.1.0
375
+ */
376
+ public function is_domain_blocked( $email ) {
377
+
378
+ if ( empty( $email ) ) {
379
+ return true;
380
+ }
381
+
382
+ $domains = trim( get_option( 'ig_es_blocked_domains', '' ) );
383
+
384
+ // No domains to block? Return
385
+ if ( empty( $domains ) ) {
386
+ return false;
387
+ }
388
+
389
+ $domains = explode( PHP_EOL, $domains );
390
+
391
+ $domains = apply_filters( 'ig_es_blocked_domains', $domains );
392
+
393
+ if ( empty( $domains ) ) {
394
+ return false;
395
+ }
396
+
397
+ $rev_email = strrev( $email );
398
+ foreach ( $domains as $item ) {
399
+ $item = trim( $item );
400
+ if ( strpos( $rev_email, strrev( $item ) ) === 0 ) {
401
+ return true;
402
+ }
403
+ }
404
+
405
+ return false;
406
+ }
407
+
408
+ /**
409
+ * Get Message description based on message
410
+ *
411
+ * @param $message
412
+ *
413
+ * @return array|mixed|string|void
414
+ *
415
+ * @since 4.0.0
416
+ */
417
+ public function get_messages( $message ) {
418
+ $ig_es_form_submission_success_message = get_option( 'ig_es_form_submission_success_message' );
419
+ $messages = array(
420
+ 'es_empty_email_notice' => __( 'Please enter email address', 'email-subscribers' ),
421
+ 'es_rate_limit_notice' => __( 'You need to wait for sometime before subscribing again', 'email-subscribers' ),
422
+ 'es_optin_success_message' => ! empty( $ig_es_form_submission_success_message ) ? $ig_es_form_submission_success_message : __( 'Successfully Subscribed.', 'email-subscribers' ),
423
+ 'es_email_exists_notice' => __( 'Email Address already exists!', 'email-subscribers' ),
424
+ 'es_unexpected_error_notice' => __( 'Oops.. Unexpected error occurred.', 'email-subscribers' ),
425
+ 'es_invalid_email_notice' => __( 'Invalid email address', 'email-subscribers' ),
426
+ 'es_invalid_name_notice' => __( 'Invalid name', 'email-subscribers' ),
427
+ 'es_try_later_notice' => __( 'Please try after some time', 'email-subscribers' ),
428
+ 'es_db_error_notice' => __( 'Oops...unable to add subscriber', 'email-subscribers' ),
429
+ 'es_permission_denied_notice' => __( 'You do not have permission to add subscriber', 'email-subscribers' ),
430
+ 'es_no_list_selected' => __( 'Please select the list', 'email-subscribers' ),
431
+ 'es_invalid_captcha' => __( 'Invalid Captcha', 'email-subscribers' )
432
+ );
433
+
434
+ $messages = apply_filters( 'ig_es_subscription_messages', $messages );
435
+
436
+ if ( ! empty( $messages ) ) {
437
+ return isset( $messages[ $message ] ) ? $messages[ $message ] : '';
438
+ }
439
+
440
+ return $messages;
441
+ }
442
+ }
443
+ }
lite/includes/classes/class-es-handle-sync-wp-user.php ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class ES_Handle_Sync_Wp_User {
4
+
5
+ public static $instance;
6
+
7
+ public function __construct() {
8
+ // Sync upcoming WordPress users
9
+ add_action( 'user_register', array( $this, 'sync_registered_wp_user' ) );
10
+ add_action( 'ig_es_sync_users_tabs_wordpress', array( $this, 'sync_wordpress_users_settings' ) );
11
+ add_action('edit_user_profile_update', array( $this, 'update_es_contact') );
12
+ }
13
+
14
+ public function sync_wordpress_users_settings( $wordpress_tab ) {
15
+
16
+ if ( ! empty( $wordpress_tab['indicator_option'] ) ) {
17
+ update_option( $wordpress_tab['indicator_option'], 'no' );
18
+ }
19
+
20
+ $submitted = ig_es_get_post_data( 'submitted' );
21
+ if ( 'submitted' === $submitted ) {
22
+
23
+ $form_data = ig_es_get_post_data( 'form_data' );
24
+
25
+ $error = false;
26
+ if ( ! empty( $form_data['es_registered'] ) && 'YES' === $form_data['es_registered'] ) {
27
+ $list_id = ! empty( $form_data['es_registered_group'] ) ? $form_data['es_registered_group'] : 0;
28
+ if ( $list_id === 0 ) {
29
+ $message = __( 'Please select list', 'email-subscribers' );
30
+ ES_Common::show_message( $message, 'error' );
31
+ $error = true;
32
+ }
33
+ }
34
+
35
+ if ( ! $error ) {
36
+ update_option( 'ig_es_sync_wp_users', $form_data );
37
+ $message = __( 'Settings have been saved successfully!', 'email-subscribers' );
38
+ ES_Common::show_message( $message, 'success' );
39
+ }
40
+ }
41
+
42
+ $default_form_data = array(
43
+ 'es_registered' => 'NO',
44
+ 'es_registered_group' => 0,
45
+ );
46
+
47
+ $form_data = get_option( 'ig_es_sync_wp_users', array() );
48
+ $form_data = wp_parse_args( $form_data, $default_form_data );
49
+
50
+ ?>
51
+
52
+ <table class="form-table">
53
+ <tbody>
54
+ <tr>
55
+ <th scope="row">
56
+ <label for="tag-image">
57
+ <?php echo __( 'Sync WordPress Users?', 'email-subscribers' ); ?>
58
+ </label>
59
+ <p class="description"><?php _e( "Whenever someone signup, it will automatically be added into selected list", 'email-subscribers' ); ?></p>
60
+ </th>
61
+ <td>
62
+ <select name="form_data[es_registered]" id="es_email_status">
63
+ <option value='NO' <?php if ( $form_data['es_registered'] == 'NO' ) {
64
+ echo "selected='selected'";
65
+ } ?>><?php echo __( 'No', 'email-subscribers' ); ?></option>
66
+ <option value='YES' <?php if ( $form_data['es_registered'] == 'YES' ) {
67
+ echo "selected='selected'";
68
+ } ?>><?php echo __( 'Yes', 'email-subscribers' ); ?></option>
69
+ </select>
70
+ </td>
71
+ </tr>
72
+ <tr>
73
+ <th>
74
+ <label for="tag-display-status">
75
+ <?php echo __( 'Select List', 'email-subscribers' ); ?>
76
+ </label>
77
+ <p class="description"><?php _e( "Select the list in which newly registered user will be subscribed to", 'email-subscribers' ); ?></p>
78
+ </th>
79
+ <td>
80
+ <select name="form_data[es_registered_group]">
81
+ <?php echo ES_Common::prepare_list_dropdown_options( $form_data['es_registered_group'], 'Select List' ); ?>
82
+ </select>
83
+ </td>
84
+ </tr>
85
+ </tbody>
86
+ </table>
87
+ <input type="hidden" name="submitted" value="submitted"/>
88
+ <p style="padding-top:5px;">
89
+ <input type="submit" class="button-primary" value="<?php echo __( 'Save Settings', 'email-subscribers' ); ?>"/>
90
+ </p>
91
+
92
+ <?php
93
+ }
94
+
95
+ public function sync_registered_wp_user( $user_id ) {
96
+ //get option
97
+ $ig_es_sync_wp_users = get_option( 'ig_es_sync_wp_users', 'norecord' );
98
+ $ig_es_sync_unserialized_data = maybe_unserialize( $ig_es_sync_wp_users );
99
+ $ig_es_registered = ( $ig_es_sync_unserialized_data != 'norecord' ) ? $ig_es_sync_unserialized_data['es_registered'] : 'NO';
100
+ if ( $ig_es_sync_wp_users != 'norecord' && 'YES' === $ig_es_registered ) {
101
+ $list_id = $ig_es_sync_unserialized_data['es_registered_group'];
102
+ //get user info
103
+ $user_info = get_userdata( $user_id );
104
+ if ( ! ( $user_info instanceof WP_User ) ) {
105
+ return false;
106
+ }
107
+ $user_firstname = $user_info->display_name;
108
+
109
+
110
+ $email = $user_info->user_email;
111
+ if ( empty( $user_firstname ) ) {
112
+ $user_firstname = ES_Common::get_name_from_email( $email );
113
+ }
114
+ //prepare data
115
+ $data = array(
116
+ 'first_name' => $user_firstname,
117
+ 'email' => $email,
118
+ 'source' => 'wp',
119
+ 'status' => 'verified',
120
+ 'hash' => ES_Common::generate_guid(),
121
+ 'created_at' => ig_get_current_date_time(),
122
+ 'wp_user_id' => $user_id
123
+ );
124
+
125
+ do_action( 'ig_es_add_contact', $data, $list_id );
126
+ }
127
+
128
+ return true;
129
+
130
+ }
131
+
132
+ public function update_es_contact( $user_id ){
133
+
134
+ $ig_es_sync_wp_users = get_option( 'ig_es_sync_wp_users', 'norecord' );
135
+ $ig_es_sync_unserialized_data = maybe_unserialize( $ig_es_sync_wp_users );
136
+ $ig_es_registered = ( $ig_es_sync_unserialized_data != 'norecord' ) ? $ig_es_sync_unserialized_data['es_registered'] : 'NO';
137
+ if ( $ig_es_sync_wp_users != 'norecord' && 'YES' === $ig_es_registered ) {
138
+ $user_info = get_userdata( $user_id );
139
+ if ( ! ( $user_info instanceof WP_User ) ) {
140
+ return;
141
+ }
142
+ //check if user exist with this email
143
+ $es_contact_id = ES()->contacts_db->get_contact_id_by_email( $user_info->user_email );
144
+ if( $es_contact_id ){
145
+ $contact['email'] = $_POST['email'];
146
+ $contact['first_name'] = $_POST['display_name'];
147
+ ES()->contacts_db->update_contact( $es_contact_id, $contact );
148
+ }
149
+ }
150
+
151
+ }
152
+
153
+ public function prepare_sync_user() {
154
+
155
+ $audience_tab_main_navigation = array();
156
+ $active_tab = 'sync';
157
+ $audience_tab_main_navigation = apply_filters( 'ig_es_audience_tab_main_navigation', $active_tab, $audience_tab_main_navigation );
158
+
159
+ ?>
160
+ <div class="wrap">
161
+ <h2> <?php _e( 'Audience > Sync Contacts', 'email-subscribers' );
162
+ ES_Common::prepare_main_header_navigation( $audience_tab_main_navigation );
163
+ ?>
164
+ </h2>
165
+ <?php $this->sync_users_callback(); ?>
166
+ </div>
167
+
168
+ <?php
169
+ }
170
+
171
+ public function sync_users_callback() {
172
+
173
+ $logger = get_ig_logger();
174
+ $logger->trace( 'Sync Users' );
175
+ $active_tab = ig_es_get_request_data( 'tab', 'wordpress' );
176
+
177
+ $tabs = array(
178
+ 'wordpress' => array(
179
+ 'name' => __( 'WordPress', 'email-subscribers' ),
180
+ 'url' => admin_url( 'admin.php?page=es_subscribers&action=sync&tab=wordpress' )
181
+ )
182
+ );
183
+
184
+ $tabs = apply_filters( 'ig_es_sync_users_tabs', $tabs );
185
+ ?>
186
+ <h2 class="nav-tab-wrapper">
187
+ <?php foreach ( $tabs as $key => $tab ) {
188
+ $tab_url = admin_url( 'admin.php?page=es_subscribers&action=sync' );
189
+ $tab_url = add_query_arg( 'tab', $key, $tab_url );
190
+
191
+ $indicator_option = ! empty( $tab['indicator_option'] ) ? $tab['indicator_option'] : '';
192
+ $indicator_label = '';
193
+ $indicator_class = '';
194
+ if ( ! empty( $indicator_option ) && ( get_option( $indicator_option, 'yes' ) == 'yes' ) ) {
195
+ $indicator_label = ! empty( $tab['indicator_label'] ) ? $tab['indicator_label'] : '';
196
+ $indicator_class = ! empty( $tab['indicator_type'] ) ? 'ig-es-indicator-' . $tab['indicator_type'] : 'ig-es-indicator-new';
197
+ }
198
+ ?>
199
+ <a class="nav-tab <?php echo $key === $active_tab ? 'nav-tab-active' : ''; ?>" href="<?php echo esc_url( $tab_url ); ?>"><?php echo esc_html__( $tab['name'] ); ?>
200
+ <?php if ( ! empty( $indicator_label ) ) { ?>
201
+ <span class="ig-es-indicator<?php echo " " . $indicator_class; ?>"><?php echo $indicator_label; ?></span>
202
+ <?php } ?>
203
+ </a>
204
+ <?php } ?>
205
+ </h2>
206
+ <form name="form_sync" id="form_sync" method="post" action="#">
207
+ <?php
208
+ $from = ! empty( $tabs[ $active_tab ]['from'] ) ? $tabs[ $active_tab ]['from'] . '_' : '';
209
+ do_action( $from . 'ig_es_sync_users_tabs_' . $active_tab, $tabs[ $active_tab ] ); ?>
210
+ </form>
211
+
212
+ <?php
213
+ }
214
+
215
+ public static function get_instance() {
216
+ if ( ! isset( self::$instance ) ) {
217
+ self::$instance = new self();
218
+ }
219
+
220
+ return self::$instance;
221
+ }
222
+
223
+ }
lite/includes/classes/class-es-import-subscribers.php ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ class ES_Import_Subscribers {
9
+ /**
10
+ * ES_Import_Subscribers constructor.
11
+ *
12
+ * @since 4.0.0
13
+ */
14
+ public function __construct() {
15
+ }
16
+
17
+ /**
18
+ * Import Contacts
19
+ *
20
+ * @since 4.0,0
21
+ *
22
+ * @modify 4.3.1
23
+ */
24
+ public function import_callback() {
25
+
26
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
27
+
28
+ $submit = ig_es_get_post_data( 'submit' );
29
+ if ( $submit ) {
30
+ $import_contacts_nonce = ig_es_get_post_data( 'import_contacts' );
31
+ if ( ! isset( $_POST['import_contacts'] ) || ! wp_verify_nonce( sanitize_key( $import_contacts_nonce ), 'import-contacts' ) ) {
32
+ $message = __( "Sorry, you do not have permission to import contacts.", 'email-subscribers' );
33
+ ES_Common::show_message( $message, 'error' );
34
+ }
35
+
36
+ if ( isset( $_FILES["file"] ) ) {
37
+
38
+ if ( is_uploaded_file( $_FILES["file"]["tmp_name"] ) ) {
39
+
40
+ $tmp_file = $_FILES["file"]["tmp_name"];
41
+ $file = $_FILES['file']['name'];
42
+
43
+ $ext = substr( $file, strrpos( $file, "." ), ( strlen( $file ) - strrpos( $file, "." ) ) );
44
+
45
+ if ( $ext == ".csv" ) {
46
+
47
+ $statuses = ES_Common::get_statuses_key_name_map();
48
+ $es_email_status = ig_es_get_post_data( 'es_email_status' );
49
+
50
+ $status = '';
51
+ if ( in_array( $es_email_status, array_keys( $statuses ) ) ) {
52
+ $status = $es_email_status;
53
+ }
54
+
55
+ if ( ! empty( $status ) ) {
56
+
57
+ $lists = ES()->lists_db->get_id_name_map();
58
+
59
+ $list_id = ig_es_get_post_data( 'list_id' );
60
+
61
+ if ( ! in_array( $list_id, array_keys( $lists ) ) ) {
62
+ $list_id = '';
63
+ }
64
+
65
+ if ( ! empty( $list_id ) ) {
66
+
67
+ $delimiter = $this->get_delimiter( $tmp_file );
68
+
69
+ $handle = fopen( $tmp_file, 'r' );
70
+
71
+ // Get Headers
72
+ $headers = array_map( 'trim', fgetcsv( $handle, 0, $delimiter ) );
73
+
74
+ $existing_contacts_email_id_map = ES()->contacts_db->get_email_id_map();
75
+
76
+ $existing_contacts = array();
77
+ if ( count( $existing_contacts_email_id_map ) > 0 ) {
78
+ $existing_contacts = array_keys( $existing_contacts_email_id_map );
79
+ }
80
+
81
+ $invalid_emails_count = $imported_subscribers_count = $existing_contacts_count = 0;
82
+ $emails = array();
83
+
84
+ $values = $place_holders = $contacts_data = array();
85
+ $current_date_time = ig_get_current_date_time();
86
+
87
+ $i = 0;
88
+ while ( ( $data = fgetcsv( $handle, 0, $delimiter ) ) !== false ) {
89
+
90
+ $data = array_map( 'trim', $data );
91
+
92
+ $data = array_combine( $headers, $data );
93
+
94
+ $email = isset( $data['Email'] ) ? sanitize_email( trim( $data['Email'] ) ) : '';
95
+
96
+ if ( empty( $email ) ) {
97
+ $invalid_emails_count ++;
98
+ continue;
99
+ }
100
+
101
+ if ( ! in_array( $email, $existing_contacts ) ) {
102
+
103
+ $name = isset( $data['Name'] ) ? trim( $data['Name'] ) : '';
104
+ $first_name = isset( $data['First Name'] ) ? sanitize_text_field( trim( $data['First Name'] ) ) : '';
105
+ $last_name = isset( $data['Last Name'] ) ? sanitize_text_field( trim( $data['Last Name'] ) ) : '';
106
+
107
+ // If we don't get the first_name & last_name, consider Name field.
108
+ // If name empty, get the name from Email
109
+ if ( empty( $first_name ) && empty( $last_name ) ) {
110
+
111
+ if ( empty( $name ) ) {
112
+ $name = ES_Common::get_name_from_email( $email );
113
+ }
114
+
115
+ $names = ES_Common::prepare_first_name_last_name( $name );
116
+ $first_name = sanitize_text_field( $names['first_name'] );
117
+ $last_name = sanitize_text_field( $names['last_name'] );
118
+ }
119
+
120
+ $guid = ES_Common::generate_guid();
121
+
122
+ $contacts_data[ $imported_subscribers_count ]['first_name'] = $first_name;
123
+ $contacts_data[ $imported_subscribers_count ]['last_name'] = $last_name;
124
+ $contacts_data[ $imported_subscribers_count ]['email'] = $email;
125
+ $contacts_data[ $imported_subscribers_count ]['source'] = 'import';
126
+ $contacts_data[ $imported_subscribers_count ]['status'] = 'verified';
127
+ $contacts_data[ $imported_subscribers_count ]['hash'] = $guid;
128
+ $contacts_data[ $imported_subscribers_count ]['created_at'] = $current_date_time;
129
+
130
+ $existing_contacts[] = $email;
131
+ } else {
132
+ $existing_contacts_count ++;
133
+ }
134
+
135
+ $emails[] = $email;
136
+ $imported_subscribers_count ++;
137
+ }
138
+
139
+ if ( count( $emails ) > 0 ) {
140
+
141
+ ES()->contacts_db->do_batch_insert( $contacts_data );
142
+
143
+ $contact_ids = ES()->contacts_db->get_contact_ids_by_emails( $emails );
144
+ if ( count( $contact_ids ) > 0 ) {
145
+ ES_DB_Lists_Contacts::delete_contacts_from_list( $list_id, $contact_ids );
146
+ ES_DB_Lists_Contacts::do_import_contacts_into_list( $list_id, $contact_ids, $status, 1, $current_date_time );
147
+ }
148
+
149
+ $message = sprintf( __( 'Total %d contacts have been imported successfully!', 'email-subscribers' ), $imported_subscribers_count );
150
+ $status = 'success';
151
+ } else {
152
+
153
+ $message = sprintf( __( 'Total %d contacts have been imported successfully!', 'email-subscribers' ), $imported_subscribers_count );
154
+
155
+ if ( $existing_contacts_count > 0 ) {
156
+ $message .= " ";
157
+ $message .= sprintf( __( '%d contacts are already exists.', 'email-subscribers' ), $existing_contacts );
158
+ }
159
+
160
+ if ( $invalid_emails_count > 0 ) {
161
+ $message .= " ";
162
+ $message .= sprintf( __( '%d contacts are invalid.', 'email-subscribers' ), $invalid_emails_count );
163
+ }
164
+
165
+ $status = 'error';
166
+ }
167
+
168
+ fclose( $handle );
169
+ ES_Common::show_message( $message, $status );
170
+
171
+ } else {
172
+ $message = __( "Error: Please Select List", 'email-subscribers' );
173
+ ES_Common::show_message( $message, 'error' );
174
+ }
175
+ } else {
176
+ $message = __( "Error: Please select status", 'email-subscribers' );
177
+ ES_Common::show_message( $message, 'error' );
178
+ }
179
+ } else {
180
+ $message = __( "Error: Please Upload only CSV File", 'email-subscribers' );
181
+ ES_Common::show_message( $message, 'error' );
182
+ }
183
+ } else {
184
+ $message = __( "Error: Please Upload File", 'email-subscribers' );
185
+ ES_Common::show_message( $message, 'error' );
186
+ }
187
+ } else {
188
+ $message = __( "Error: Please Upload File", 'email-subscribers' );
189
+ ES_Common::show_message( $message, 'error' );
190
+ }
191
+ }
192
+
193
+ $this->prepare_import_subscriber_form();
194
+
195
+ }
196
+
197
+ public function prepare_import_subscriber_form() {
198
+
199
+ ?>
200
+
201
+ <div class="tool-box">
202
+ <form name="form_addemail" id="form_addemail" method="post" action="#" enctype="multipart/form-data">
203
+ <table class="form-table">
204
+ <tbody>
205
+ <tr>
206
+ <th scope="row">
207
+ <label for="tag-image"><?php _e( 'Select CSV file', 'email-subscribers' ); ?>
208
+ <p class="description">
209
+ <?php _e( 'Check CSV structure', 'email-subscribers' ); ?>
210
+ <a target="_blank" href="<?php echo plugin_dir_url( __FILE__ ) . '../../admin/partials/sample.csv'; ?>"><?php _e( 'from here', 'email-subscribers' ); ?></a>
211
+ </p>
212
+ </label>
213
+ </th>
214
+ <td>
215
+ <input type="file" name="file" id="file"/>
216
+ </td>
217
+ </tr>
218
+ <tr>
219
+ <th scope="row">
220
+ <label for="tag-email-status">
221
+ <?php _e( 'Select status', 'email-subscribers' ); ?> <p></p>
222
+ </label>
223
+ </th>
224
+ <td>
225
+ <select name="es_email_status" id="es_email_status">
226
+ <?php echo ES_Common::prepare_statuses_dropdown_options(); ?>
227
+ </select>
228
+ </td>
229
+ </tr>
230
+ <tr>
231
+ <th>
232
+ <label for="tag-email-group">
233
+ <?php _e( 'Select list', 'email-subscribers' ); ?>
234
+ </label>
235
+ </th>
236
+ <td>
237
+ <select name="list_id" id="list_id">
238
+ <?php echo ES_Common::prepare_list_dropdown_options(); ?>
239
+ </select>
240
+ </td>
241
+ </tr>
242
+ </tbody>
243
+ </table>
244
+ <p style="padding-top:10px;">
245
+ <?php wp_nonce_field( 'import-contacts', 'import_contacts' ); ?>
246
+ <input type="submit" name="submit" class="button-primary" value=<?php _e( "Import", 'email-subscribers' ); ?>>
247
+ </p>
248
+ </form>
249
+ </div>
250
+
251
+ <?php
252
+ }
253
+
254
+ /**
255
+ * Show import contacts
256
+ *
257
+ * @since 4.0.0
258
+ */
259
+ public function import_subscribers_page() {
260
+
261
+ $audience_tab_main_navigation = array();
262
+ $active_tab = 'import';
263
+ $audience_tab_main_navigation = apply_filters( 'ig_es_audience_tab_main_navigation', $active_tab, $audience_tab_main_navigation );
264
+
265
+ ?>
266
+
267
+ <div class="wrap">
268
+ <h2> <?php _e( 'Audience > Import Contacts', 'email-subscribers' );
269
+
270
+ ES_Common::prepare_main_header_navigation( $audience_tab_main_navigation );
271
+ ?>
272
+
273
+ </h2>
274
+ <?php $this->import_callback(); ?>
275
+ </div>
276
+
277
+ <?php
278
+ }
279
+
280
+ /**
281
+ * Get CSV file delimiter
282
+ *
283
+ * @param $file
284
+ * @param int $check_lines
285
+ *
286
+ * @return mixed
287
+ *
288
+ * @since 4.3.1
289
+ */
290
+ function get_delimiter( $file, $check_lines = 2 ) {
291
+
292
+ $file = new SplFileObject( $file );
293
+
294
+ $delimiters = array( ',', '\t', ';', '|', ':' );
295
+ $results = array();
296
+ $i = 0;
297
+ while ( $file->valid() && $i <= $check_lines ) {
298
+ $line = $file->fgets();
299
+ foreach ( $delimiters as $delimiter ) {
300
+ $regExp = '/[' . $delimiter . ']/';
301
+ $fields = preg_split( $regExp, $line );
302
+ if ( count( $fields ) > 1 ) {
303
+ if ( ! empty( $results[ $delimiter ] ) ) {
304
+ $results[ $delimiter ] ++;
305
+ } else {
306
+ $results[ $delimiter ] = 1;
307
+ }
308
+ }
309
+ }
310
+ $i ++;
311
+ }
312
+ $results = array_keys( $results, max( $results ) );
313
+
314
+ return $results[0];
315
+ }
316
+
317
+ }
318
+
lite/includes/classes/class-es-info.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ class ES_Info {
9
+
10
+ static $instance;
11
+
12
+ public function __construct() {
13
+ add_action( 'admin_menu', array( $this, 'plugin_menu' ) );
14
+ }
15
+
16
+ public function plugin_menu() {
17
+ $help_title = __( 'Help & Info', 'email-subscribers' );
18
+ add_submenu_page( 'es_dashboard', $help_title, $help_title, 'edit_posts', 'es_general_information', array( $this, 'es_information_callback' ) );
19
+
20
+ $pro_title = __( '<span class="es-fire-sale"> 🔥 </span> Go Pro', 'email-subscribers' );
21
+ if( ! ES()->is_pro() ){
22
+ add_submenu_page( 'es_dashboard', $pro_title, $pro_title, 'edit_posts', 'es_pricing', array( $this, 'es_pricing_callback' ) );
23
+ }
24
+ }
25
+
26
+ public function es_information_callback() {
27
+
28
+ $is_option_exists = get_option( 'current_sa_email_subscribers_db_version', false );
29
+ $enable_manual_update = false;
30
+ if ( $is_option_exists ) {
31
+ $enable_manual_update = true;
32
+ }
33
+
34
+ $update_url = add_query_arg( 'do_update_ig_es', 'true', admin_url( 'admin.php?page=es_general_information' ) );
35
+ $update_url = add_query_arg( 'from_db_version', '3.5.18', $update_url );
36
+ $update_url = wp_nonce_url( $update_url, 'ig_es_db_update', 'ig_es_db_update_nonce' );
37
+
38
+ include_once( ES_PLUGIN_DIR . '/lite/admin/partials/help.php' );
39
+ }
40
+
41
+ public static function es_pricing_callback() {
42
+ //remove because of warning
43
+ // $url = 'https://www.icegram.com/email-subscribers-pricing/';
44
+ // header('Location: ' . $url );
45
+ }
46
+
47
+ public static function get_instance() {
48
+ if ( ! isset( self::$instance ) ) {
49
+ self::$instance = new self();
50
+ }
51
+
52
+ return self::$instance;
53
+ }
54
+
55
+ }
lite/includes/classes/class-es-lists-table.php ADDED
@@ -0,0 +1,640 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ if ( ! class_exists( 'WP_List_Table' ) ) {
9
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
10
+ }
11
+
12
+ class ES_Lists_Table extends WP_List_Table {
13
+ /**
14
+ * ES_DB_Lists object
15
+ *
16
+ * @since 4.2.1
17
+ * @var $db
18
+ *
19
+ */
20
+ protected $db;
21
+ /**
22
+ * @since 4.2.1
23
+ * @var string
24
+ *
25
+ */
26
+ public static $option_per_page = 'es_lists_per_page';
27
+
28
+ /**
29
+ * ES_Lists_Table constructor.
30
+ *
31
+ * @since 4.0
32
+ */
33
+ public function __construct() {
34
+
35
+ parent::__construct( array(
36
+ 'singular' => __( 'List', 'email-subscribers' ), //singular name of the listed records
37
+ 'plural' => __( 'Lists', 'email-subscribers' ), //plural name of the listed records
38
+ 'ajax' => false, //does this table support ajax?,
39
+ 'screen' => 'es_lists'
40
+ ) );
41
+
42
+ $this->db = new ES_DB_Lists();
43
+ }
44
+
45
+ /**
46
+ * Add Screen Option
47
+ *
48
+ * @since 4.2.1
49
+ */
50
+ public static function screen_options() {
51
+
52
+ $option = 'per_page';
53
+ $args = array(
54
+ 'label' => __( 'Number of lists per page', 'email-subscribers' ),
55
+ 'default' => 20,
56
+ 'option' => self::$option_per_page
57
+ );
58
+
59
+ add_screen_option( $option, $args );
60
+
61
+ }
62
+
63
+ public function render() {
64
+
65
+ $action = ig_es_get_request_data( 'action' );
66
+
67
+ ?>
68
+ <div class="wrap">
69
+ <?php if ( 'new' === $action ) {
70
+ $this->es_new_lists_callback();
71
+ } elseif ( 'edit' === $action ) {
72
+ $list = ig_es_get_request_data( 'list' );
73
+ echo $this->edit_list( absint( $list ) );
74
+ } else { ?>
75
+ <h1 class="wp-heading-inline"><?php _e( 'Audience > Lists', 'email-subscribers' ); ?> <a href="admin.php?page=es_lists&action=new" class="page-title-action">Add New</a></h1>
76
+ <?php Email_Subscribers_Admin::es_feedback(); ?>
77
+ <div id="poststuff">
78
+ <div id="post-body" class="metabox-holder column-1">
79
+ <div id="post-body-content">
80
+ <div class="meta-box-sortables ui-sortable">
81
+ <form method="post">
82
+ <?php
83
+ $this->prepare_items();
84
+ $this->display(); ?>
85
+ </form>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ <br class="clear">
90
+ </div>
91
+ </div>
92
+ <?php }
93
+ }
94
+
95
+ /**
96
+ * Validate data
97
+ *
98
+ * @param $data
99
+ *
100
+ * @return array
101
+ */
102
+ public function validate_data( $data ) {
103
+
104
+ $nonce = $data['nonce'];
105
+ $list_name = $data['list_name'];
106
+
107
+ $status = 'error';
108
+ $message = '';
109
+ if ( ! wp_verify_nonce( $nonce, 'es_list' ) ) {
110
+ $message = __( 'You do not have permission to edit list', 'email-subscribers' );
111
+ } elseif ( empty( $list_name ) ) {
112
+ $message = __( 'Please add list name', 'email-subscribers' );
113
+ } elseif ( $this->db->is_list_exists( $list_name ) ) {
114
+ $message = __( 'List already exists. Please choose different name', 'email-subscribers' );
115
+ } else {
116
+ $status = 'success';
117
+ }
118
+
119
+ $response = array(
120
+ 'status' => $status,
121
+ 'message' => $message
122
+ );
123
+
124
+ return $response;
125
+
126
+ }
127
+
128
+ public function es_new_lists_callback() {
129
+
130
+ $submitted = ig_es_get_request_data( 'submitted' );
131
+
132
+ if ( 'submitted' === $submitted ) {
133
+
134
+ $nonce = ig_es_get_request_data( '_wpnonce' );
135
+ $list_name = ig_es_get_request_data( 'list_name' );
136
+
137
+ $validate_data = array(
138
+ 'nonce' => $nonce,
139
+ 'list_name' => $list_name,
140
+ );
141
+
142
+ $response = $this->validate_data( $validate_data );
143
+
144
+ if ( 'error' === $response['status'] ) {
145
+ $message = $response['message'];
146
+ ES_Common::show_message( $message, 'error' );
147
+ $this->prepare_list_form( null, $validate_data );
148
+
149
+ return;
150
+ }
151
+
152
+ $data = array(
153
+ 'list_name' => $list_name,
154
+ );
155
+
156
+ $save = $this->save_list( null, $data );
157
+
158
+ if ( $save ) {
159
+ $message = __( 'List has been added successfully!', 'email-subscribers' );
160
+ ES_Common::show_message( $message, 'success' );
161
+ } else {
162
+
163
+ }
164
+ }
165
+
166
+ $this->prepare_list_form();
167
+ }
168
+
169
+ /**
170
+ * Edit List
171
+ *
172
+ * @param $id
173
+ *
174
+ * @since 4.0.0
175
+ */
176
+ public function edit_list( $id ) {
177
+
178
+ $list = $this->db->get( $id );
179
+
180
+ $submitted = ig_es_get_request_data( 'submitted' );
181
+
182
+ if ( 'submitted' === $submitted ) {
183
+
184
+ $nonce = ig_es_get_request_data( '_wpnonce' );
185
+ $list_name = ig_es_get_request_data( 'list_name' );
186
+
187
+ $validate_data = array(
188
+ 'nonce' => $nonce,
189
+ 'list_name' => $list_name,
190
+ );
191
+
192
+ $response = $this->validate_data( $validate_data );
193
+
194
+ if ( 'error' === $response['status'] ) {
195
+ $message = $response['message'];
196
+ ES_Common::show_message( $message, 'error' );
197
+ $this->prepare_list_form( $id, $validate_data );
198
+
199
+ return;
200
+ }
201
+
202
+ $data = array(
203
+ 'list_name' => $list_name,
204
+ );
205
+
206
+ $save = $this->save_list( $id, $data );
207
+ if ( $save ) {
208
+ $message = __( 'List has been updated successfully!', 'email-subscribers' );
209
+ ES_Common::show_message( $message, 'success' );
210
+ } else {
211
+
212
+ }
213
+ } else {
214
+
215
+ $id = $list['id'];
216
+
217
+ $data = array(
218
+ 'list_name' => $list['name'],
219
+ );
220
+
221
+ }
222
+
223
+ $this->prepare_list_form( $id, $data );
224
+
225
+ ?>
226
+
227
+ <?php
228
+ }
229
+
230
+ public function prepare_list_form( $id = 0, $data = array() ) {
231
+
232
+ $is_new = empty( $id ) ? 1 : 0;
233
+
234
+ $action = 'new';
235
+ if ( ! $is_new ) {
236
+ $action = 'edit';
237
+ }
238
+
239
+ $list_name = isset( $data['list_name'] ) ? $data['list_name'] : '';
240
+
241
+ $nonce = wp_create_nonce( 'es_list' );
242
+
243
+ ?>
244
+
245
+ <div class="wrap">
246
+ <h1 class="wp-heading-inline">
247
+ <?php
248
+ if ( $is_new ) {
249
+ _e( 'Add New', 'email-subscribers' );
250
+ } else {
251
+ _e( 'Edit List', 'email-subscribers' );
252
+ }
253
+
254
+ ?>
255
+ <a href="admin.php?page=es_lists&action=manage-lists" class="page-title-action es-imp-button"><?php _e( 'Manage Lists', 'email-subscribers' ); ?></a>
256
+ </h1>
257
+
258
+ <?php Email_Subscribers_Admin::es_feedback(); ?>
259
+
260
+ <div id="poststuff">
261
+ <div id="post-body" class="metabox-holder column-1">
262
+ <div id="post-body-content">
263
+ <div class="meta-box-sortables ui-sortable">
264
+ <form method="post" action="admin.php?page=es_lists&action=<?php echo $action; ?>&list=<?php echo $id; ?>&_wpnonce=<?php echo $nonce; ?>">
265
+ <div class="row-blog">
266
+ <label><?php _e( 'Name', 'email-subscribers' ); ?>: </label>
267
+ <input type="text" id="name" name="list_name" value="<?php echo $list_name; ?>"/>
268
+ </div>
269
+ <input type="hidden" name="submitted" value="submitted"/>
270
+ <div class="row-blog"><?php submit_button(); ?></div>
271
+ </form>
272
+ </div>
273
+ </div>
274
+ </div>
275
+ <br class="clear">
276
+ </div>
277
+ </div>
278
+
279
+ <?php
280
+
281
+ }
282
+
283
+ /**
284
+ * Save list
285
+ *
286
+ * @param $id
287
+ * @param $data
288
+ *
289
+ * @return bool|int|void
290
+ *
291
+ * @since 4.0.0
292
+ */
293
+ public function save_list( $id, $data ) {
294
+ $name = sanitize_text_field( $data['list_name'] );
295
+
296
+ if ( ! empty( $id ) ) {
297
+ $return = $this->db->update_list( $id, $name );
298
+ } else {
299
+ $return = $this->db->add_list( $name );
300
+ }
301
+
302
+ /*
303
+ $list_data['name'] = sanitize_text_field( $data['list_name'] );
304
+ $list_data['slug'] = sanitize_title( $list_data['name'] );
305
+ $list_data['created_at'] = ig_get_current_date_time();
306
+
307
+ if ( ! empty( $id ) ) {
308
+ $return = $wpdb->update( IG_LISTS_TABLE, $list_data, array( 'id' => $id ) );
309
+ } else {
310
+ $return = $wpdb->insert( IG_LISTS_TABLE, $list_data );
311
+ }
312
+ */
313
+
314
+ return $return;
315
+ }
316
+
317
+ /**
318
+ * Retrieve lists data from the database
319
+ *
320
+ * @param int $per_page
321
+ * @param int $page_number
322
+ *
323
+ * @return mixed
324
+ */
325
+ public function get_lists( $per_page = 5, $page_number = 1, $do_count_only = false ) {
326
+
327
+ global $wpdb;
328
+
329
+ $order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
330
+ $order = ig_es_get_request_data( 'order' );
331
+ $search = ig_es_get_request_data( 's' );
332
+
333
+ if ( $do_count_only ) {
334
+ $sql = "SELECT count(*) as total FROM " . IG_LISTS_TABLE;
335
+ } else {
336
+ $sql = "SELECT * FROM " . IG_LISTS_TABLE;
337
+ }
338
+
339
+ $args = $query = array();
340
+
341
+ $add_where_clause = false;
342
+
343
+ if ( ! empty( $search ) ) {
344
+ $query[] = " name LIKE %s ";
345
+ $args[] = "%" . $wpdb->esc_like( $search ) . "%";
346
+
347
+ $add_where_clause = true;
348
+ }
349
+
350
+ if ( $add_where_clause ) {
351
+ $sql .= " WHERE ";
352
+
353
+ if ( count( $query ) > 0 ) {
354
+ $sql .= implode( " AND ", $query );
355
+ if ( count( $args ) > 0 ) {
356
+ $sql = $wpdb->prepare( $sql, $args );
357
+ }
358
+ }
359
+ }
360
+
361
+ if ( ! $do_count_only ) {
362
+
363
+ // Prepare Order by clause
364
+ $order = ! empty( $order ) ? strtolower( $order ) : 'desc';
365
+ $expected_order_values = array( 'asc', 'desc' );
366
+ if ( ! in_array( $order, $expected_order_values ) ) {
367
+ $order = 'desc';
368
+ }
369
+
370
+ $default_order_by = esc_sql( 'created_at' );
371
+
372
+ $expected_order_by_values = array( 'name', 'created_at' );
373
+
374
+ if ( ! in_array( $order_by, $expected_order_by_values ) ) {
375
+ $order_by_clause = " ORDER BY {$default_order_by} DESC";
376
+ } else {
377
+ $order_by = esc_sql( $order_by );
378
+ $order_by_clause = " ORDER BY {$order_by} {$order}, {$default_order_by} DESC";
379
+ }
380
+
381
+ $sql .= $order_by_clause;
382
+ $sql .= " LIMIT $per_page";
383
+ $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
384
+
385
+ $result = $wpdb->get_results( $sql, 'ARRAY_A' );
386
+
387
+ } else {
388
+ $result = $wpdb->get_var( $sql );
389
+ }
390
+
391
+ return $result;
392
+ }
393
+
394
+
395
+ /**
396
+ * Returns the count of records in the database.
397
+ *
398
+ * @return null|string
399
+ */
400
+ public function record_count() {
401
+ global $wpdb;
402
+
403
+ $sql = "SELECT COUNT(*) FROM " . IG_LISTS_TABLE;
404
+
405
+ return $wpdb->get_var( $sql );
406
+ }
407
+
408
+ /**
409
+ * Render a column when no column specific method exist.
410
+ *
411
+ * @param array $item
412
+ * @param string $column_name
413
+ *
414
+ * @return mixed
415
+ */
416
+ public function column_default( $item, $column_name ) {
417
+
418
+ switch ( $column_name ) {
419
+ case 'active_contacts':
420
+ $count = ES_DB_Lists_Contacts::get_total_count_by_list( $item['id'], 'subscribed' );
421
+ if ( $count > 0 ) {
422
+ $url = admin_url( 'admin.php?page=es_subscribers&filter_by_status=subscribed&filter_by_list_id=' . $item['id'] );
423
+ $count = sprintf( __( '<a href="%s" target="_blank">%d</a>', 'email-subscribers' ), $url, $count );
424
+ }
425
+
426
+ return $count;
427
+ break;
428
+ case 'all_contacts':
429
+ $count = ES_DB_Lists_Contacts::get_total_count_by_list( $item['id'], 'all' );
430
+ if ( $count > 0 ) {
431
+ $url = admin_url( 'admin.php?page=es_subscribers&filter_by_list_id=' . $item['id'] );
432
+ $count = sprintf( __( '<a href="%s" target="_blank">%d</a>', 'email-subscribers' ), $url, $count );
433
+ }
434
+
435
+ return $count;
436
+ break;
437
+ case 'created_at':
438
+ return ig_es_format_date_time( $item[ $column_name ] );
439
+ break;
440
+
441
+ case 'export':
442
+ return "<a href='admin.php?page=download_report&report=users&status=select_list&list_id={$item['id']}'>" . __( 'Download', 'email-subscribers' ) . '</a>';
443
+ default:
444
+ return '';
445
+ }
446
+ }
447
+
448
+ /**
449
+ * Render the bulk edit checkbox
450
+ *
451
+ * @param array $item
452
+ *
453
+ * @return string
454
+ */
455
+ function column_cb( $item ) {
456
+ return sprintf(
457
+ '<input type="checkbox" name="lists[]" value="%s" />', $item['id']
458
+ );
459
+ }
460
+
461
+ /**
462
+ * Method for name column
463
+ *
464
+ * @param array $item an array of DB data
465
+ *
466
+ * @return string
467
+ */
468
+ function column_name( $item ) {
469
+
470
+ $list_nonce = wp_create_nonce( 'es_list' );
471
+
472
+ $title = '<strong>' . $item['name'] . '</strong>';
473
+ $actions = array();
474
+ if ( $item['id'] != 1 ) {
475
+ $page = ig_es_get_request_data( 'page' );
476
+ $actions = array(
477
+ 'edit' => sprintf( __( '<a href="?page=%s&action=%s&list=%s&_wpnonce=%s">Edit</a>', 'email-subscribers' ), esc_attr( $page ), 'edit', absint( $item['id'] ), $list_nonce ),
478
+ 'delete' => sprintf( __( '<a href="?page=%s&action=%s&list=%s&_wpnonce=%s" onclick="return checkDelete()">Delete</a>', 'email-subscribers' ), esc_attr( $page ), 'delete', absint( $item['id'] ), $list_nonce )
479
+ );
480
+ }
481
+
482
+ return $title . $this->row_actions( $actions );
483
+ }
484
+
485
+
486
+ /**
487
+ * Associative array of columns
488
+ *
489
+ * @return array
490
+ */
491
+ function get_columns() {
492
+ $columns = array(
493
+ 'cb' => '<input type="checkbox" />',
494
+ 'name' => __( 'Name', 'email-subscribers' ),
495
+ 'active_contacts' => __( 'Active Contacts', 'email-subscribers' ),
496
+ 'all_contacts' => __( 'All Contacts', 'email-subscribers' ),
497
+ 'created_at' => __( 'Created', 'email-subscribers' ),
498
+ 'export' => __( 'Export', 'email-subscribers' )
499
+ );
500
+
501
+ return $columns;
502
+ }
503
+
504
+
505
+ /**
506
+ * Columns to make sortable.
507
+ *
508
+ * @return array
509
+ */
510
+ public function get_sortable_columns() {
511
+ $sortable_columns = array(
512
+ 'name' => array( 'name', true ),
513
+ 'created_at' => array( 'created_at', true ),
514
+ );
515
+
516
+ return $sortable_columns;
517
+ }
518
+
519
+ /**
520
+ * Returns an associative array containing the bulk action
521
+ *
522
+ * @return array
523
+ */
524
+ public function get_bulk_actions() {
525
+ $actions = array(
526
+ 'bulk_delete' => __( 'Delete', 'email-subscribers' )
527
+ );
528
+
529
+ return $actions;
530
+ }
531
+
532
+ public function search_box( $text, $input_id ) { ?>
533
+ <p class="search-box">
534
+ <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
535
+ <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>"/>
536
+ <?php submit_button( __( 'Search Lists', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
537
+ </p>
538
+ <?php }
539
+
540
+ /**
541
+ * Handles data query and filter, sorting, and pagination.
542
+ */
543
+ public function prepare_items() {
544
+
545
+ $this->_column_headers = $this->get_column_info();
546
+
547
+ /** Process bulk action */
548
+ $this->process_bulk_action();
549
+ $this->search_box( ig_es_get_request_data( 's' ), 'list-search-input' );
550
+
551
+ $per_page = $this->get_items_per_page( self::$option_per_page, 10 );
552
+ $current_page = $this->get_pagenum();
553
+ $total_items = $this->get_lists( 0, 0, true );
554
+
555
+ $this->set_pagination_args( array(
556
+ 'total_items' => $total_items, //WE have to calculate the total number of items
557
+ 'per_page' => $per_page //WE have to determine how many items to show on a page
558
+ ) );
559
+
560
+ $this->items = $this->get_lists( $per_page, $current_page );
561
+ }
562
+
563
+ public function process_bulk_action() {
564
+
565
+ //Detect when a bulk action is being triggered...
566
+ if ( 'edit' === $this->current_action() ) {
567
+
568
+ // In our file that handles the request, verify the nonce.
569
+ $nonce = esc_attr( ig_es_get_request_data( '_wpnonce' ) );
570
+
571
+ if ( ! wp_verify_nonce( $nonce, 'es_list' ) ) {
572
+ $message = __( 'You do not have permission to edit list', 'email-subscribers' );
573
+ ES_Common::show_message( $message, 'error' );
574
+ } else {
575
+ $this->edit_list( absint( ig_es_get_request_data( 'list' ) ) );
576
+ $message = __( 'List has been updated successfully!', 'email-subscribers' );
577
+ ES_Common::show_message( $message, 'success' );
578
+ }
579
+
580
+ }
581
+
582
+ if ( 'delete' === $this->current_action() ) {
583
+
584
+ // In our file that handles the request, verify the nonce.
585
+ $nonce = esc_attr( ig_es_get_request_data( '_wpnonce' ) );
586
+
587
+ if ( ! wp_verify_nonce( $nonce, 'es_list' ) ) {
588
+ $message = __( 'You do not have permission to delete list', 'email-subscribers' );
589
+ ES_Common::show_message( $message, 'error' );
590
+ } else {
591
+ $list = ig_es_get_request_data( 'list' );
592
+ if ( $list != 1 ) {
593
+ $list = ig_es_get_request_data( 'list' );
594
+ $this->db->delete_lists( array( $list ) );
595
+ $message = __( 'List has been deleted successfully!', 'email-subscribers' );
596
+ ES_Common::show_message( $message, 'success' );
597
+ }
598
+ }
599
+ }
600
+
601
+ $action = ig_es_get_request_data( 'action' );
602
+ $action2 = ig_es_get_request_data( 'action2' );
603
+ // If the delete bulk action is triggered
604
+ if ( ( 'bulk_delete' === $action ) || ( 'bulk_delete' === $action2 ) ) {
605
+
606
+ $lists = ig_es_get_request_data( 'lists' );
607
+
608
+ if ( ! empty( $lists ) > 0 ) {
609
+ $this->db->delete_lists( $lists );
610
+ $message = __( 'List(s) have been deleted successfully', 'email-subscribers' );
611
+ ES_Common::show_message( $message, 'success' );
612
+ } else {
613
+ $message = __( 'Please select list', 'email-subscribers' );
614
+ ES_Common::show_message( $message, 'error' );
615
+
616
+ return;
617
+ }
618
+ }
619
+ }
620
+
621
+ public function status_label_map( $status ) {
622
+
623
+ $statuses = array(
624
+ 'enable' => __( 'Enable', 'email-subscribers' ),
625
+ 'disable' => __( 'Disable', 'email-subscribers' )
626
+ );
627
+
628
+ if ( ! in_array( $status, array_keys( $statuses ) ) ) {
629
+ return '';
630
+ }
631
+
632
+ return $statuses[ $status ];
633
+ }
634
+
635
+ /** Text displayed when no list data is available */
636
+ public function no_items() {
637
+ _e( 'No lists avaliable.', 'email-subscribers' );
638
+ }
639
+
640
+ }
lite/includes/classes/class-es-mailer.php ADDED
@@ -0,0 +1,1146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ if ( ! class_exists( 'ES_Mailer' ) ) {
9
+ /**
10
+ * Class ES_Mailer_New
11
+ *
12
+ * @since 4.0.0
13
+ * @since 4.3.2 Modified structure. Made it OOP based
14
+ */
15
+ class ES_Mailer {
16
+ /**
17
+ * Store Link data
18
+ *
19
+ * @since 4.3.2
20
+ * @var array
21
+ *
22
+ */
23
+ var $link_data = array();
24
+
25
+ /**
26
+ * Is limits set?
27
+ *
28
+ * @since 4.3.2
29
+ * @var bool
30
+ *
31
+ */
32
+ var $limits_set = false;
33
+
34
+ /**
35
+ * Max execution time
36
+ *
37
+ * @since 4.3.2
38
+ * @var int
39
+ *
40
+ */
41
+ var $time_limit = 0;
42
+
43
+ /**
44
+ * Start time of email sending
45
+ *
46
+ * @since 4.3.2
47
+ * @var int
48
+ *
49
+ */
50
+ var $time_start = 0;
51
+
52
+ /**
53
+ * Maximum email send count
54
+ *
55
+ * @since 4.3.2
56
+ * @var int
57
+ *
58
+ */
59
+ var $email_limit = 0;
60
+
61
+ /**
62
+ * Keep map of email => id data
63
+ *
64
+ * @since 4.3.2
65
+ * @var array
66
+ *
67
+ */
68
+ var $email_id_map = array();
69
+
70
+ /**
71
+ * @since 4.3.2
72
+ * @var bool
73
+ *
74
+ */
75
+ var $add_unsubscribe_link = true;
76
+
77
+ /**
78
+ * @since 4.3.2
79
+ * @var bool
80
+ *
81
+ */
82
+ var $add_tracking_pixel = true;
83
+
84
+ /**
85
+ * Added Logger Context
86
+ *
87
+ * @since 4.3.2
88
+ * @var array
89
+ *
90
+ */
91
+ public $logger_context = array(
92
+ 'source' => 'ig_es_mailer'
93
+ );
94
+
95
+ /**
96
+ * @since 4.3.2
97
+ * @var object|ES_Base_Mailer
98
+ */
99
+ var $mailer;
100
+
101
+ /**
102
+ * ES_Mailer constructor.
103
+ *
104
+ * @since 4.3.2
105
+ */
106
+ public function __construct() {
107
+
108
+ $ig_es_mailer_settings = get_option( 'ig_es_mailer_settings', array() );
109
+
110
+ $mailer = ! empty( $ig_es_mailer_settings['mailer'] ) ? $ig_es_mailer_settings['mailer'] : 'wpmail';
111
+
112
+ $mailer_class = 'ES_' . ucfirst( $mailer ) . '_Mailer';
113
+
114
+ // If we don't found mailer class, fallback to WP Mail.
115
+ if ( ! class_exists( $mailer_class ) ) {
116
+ $mailer_class = 'ES_Wpmail_Mailer';
117
+ }
118
+
119
+ $this->mailer = new $mailer_class();
120
+ }
121
+
122
+ /**
123
+ * Check whether max execution time reaches to it's maximum or
124
+ * reached email quota
125
+ *
126
+ * @return bool
127
+ *
128
+ * @since 4.3.2
129
+ */
130
+ public function limits_exceeded() {
131
+
132
+ if ( ! $this->limits_set ) {
133
+
134
+ @set_time_limit( IG_ES_CRON_INTERVAL + 30 );
135
+
136
+ // Set 95% of max_execution_time as a max limit. We can reduce it as well
137
+ $max_time = (int) ( @ini_get( 'max_execution_time' ) * 0.95 );
138
+ if ( $max_time == 0 || $max_time > IG_ES_CRON_INTERVAL ) {
139
+ $max_time = (int) ( IG_ES_CRON_INTERVAL * 0.95 );
140
+ }
141
+
142
+ $this->time_limit = $this->time_start + $max_time;
143
+
144
+ $this->email_limit = ES_Common::total_emails_to_be_sent();
145
+
146
+ // We are doing heavy lifting..allocate more memory
147
+ if ( function_exists( 'memory_get_usage' ) && ( (int) @ini_get( 'memory_limit' ) < 128 ) ) {
148
+ @ini_set( 'memory_limit', '256M' );
149
+ }
150
+
151
+ $this->limits_set = true;
152
+ }
153
+
154
+ if ( time() > $this->time_limit ) {
155
+ return true;
156
+ }
157
+
158
+ if ( $this->email_limit <= 0 ) {
159
+ return true;
160
+ }
161
+
162
+ return false;
163
+ }
164
+
165
+ /**
166
+ * Send Sign up Notifications to admins
167
+ *
168
+ * @param $data
169
+ *
170
+ * @return bool
171
+ *
172
+ * @since 4.3.2
173
+ */
174
+ public function send_add_new_contact_notification_to_admins( $data ) {
175
+
176
+ if ( ! $this->can_send_add_new_contact_notification() ) {
177
+ return false;
178
+ }
179
+
180
+ $admin_emails = $this->get_admin_emails();
181
+
182
+ if ( ! empty( $admin_emails ) && is_array( $admin_emails ) && count( $admin_emails ) > 0 ) {
183
+
184
+ $subject = $this->get_admin_new_contact_email_subject();
185
+ $content = $this->get_admin_new_contact_email_content();
186
+
187
+ $this->add_unsubscribe_link = false;
188
+ $this->add_tracking_pixel = false;
189
+ $this->send( $subject, $content, $admin_emails, $data );
190
+
191
+ return true;
192
+ }
193
+
194
+ return false;
195
+ }
196
+
197
+
198
+ /**
199
+ * Get new contact email subject
200
+ *
201
+ * @return string
202
+ *
203
+ * @since 4.3.2
204
+ */
205
+ public function get_admin_new_contact_email_subject() {
206
+ return stripslashes( get_option( 'ig_es_admin_new_contact_email_subject', '' ) );
207
+ }
208
+
209
+ /**
210
+ * Get new contact email content
211
+ *
212
+ * @return string
213
+ *
214
+ * @since 4.3.2
215
+ */
216
+ public function get_admin_new_contact_email_content() {
217
+ return wpautop( stripslashes( get_option( 'ig_es_admin_new_contact_email_content', '' ) ) );
218
+ }
219
+
220
+ /**
221
+ * Can send add new contact to admin?
222
+ *
223
+ * @return bool
224
+ *
225
+ * @since 4.3.2
226
+ */
227
+ public function can_send_add_new_contact_notification() {
228
+ $ig_es_notify_admin = get_option( 'ig_es_notify_admin', 'no' );
229
+
230
+ if ( 'yes' === $ig_es_notify_admin ) {
231
+ return true;
232
+ }
233
+
234
+ return false;
235
+ }
236
+
237
+ /**
238
+ * Send Double Optin Email
239
+ *
240
+ * @param $emails
241
+ * @param array $merge_tags
242
+ *
243
+ * @since 4.3.2
244
+ */
245
+ public function send_double_optin_email( $emails, $merge_tags = array() ) {
246
+
247
+ $subject = $this->get_confirmation_email_subject();
248
+ $content = $this->get_confirmation_email_content();
249
+
250
+ $content = str_replace( "{{LINK}}", "{{SUBSCRIBE-LINK}}", $content );
251
+
252
+ if ( empty( $subject ) || empty( $content ) ) {
253
+ return false;
254
+ }
255
+
256
+ $this->add_unsubscribe_link = false;
257
+ $this->add_tracking_pixel = false;
258
+
259
+ return $this->send( $subject, $content, $emails, $merge_tags );
260
+ }
261
+
262
+ /**
263
+ * Get Confirmation Email Content
264
+ *
265
+ * @return string
266
+ *
267
+ * @since 4.3.2
268
+ */
269
+ public function get_confirmation_email_content() {
270
+ return wpautop( stripslashes( get_option( 'ig_es_confirmation_mail_content', '' ) ) );
271
+ }
272
+
273
+ /**
274
+ * Get Confirmation Email Subject
275
+ *
276
+ * @return string
277
+ *
278
+ * @since 4.3.2
279
+ */
280
+ public function get_confirmation_email_subject() {
281
+ return stripslashes( get_option( 'ig_es_confirmation_mail_subject', '' ) );
282
+ }
283
+
284
+ /**
285
+ * Send Cron Admin Emails
286
+ *
287
+ * @param string $notification_guid
288
+ *
289
+ * @since 4.3.2
290
+ */
291
+ public function send_cron_admin_email( $notification_guid = '' ) {
292
+
293
+ if ( ! $this->can_send_cron_admin_email() ) {
294
+ return;
295
+ }
296
+
297
+ $admin_emails = $this->get_admin_emails();
298
+
299
+ if ( ! empty( $admin_emails ) && ! empty( $notification_guid ) && is_array( $admin_emails ) && count( $admin_emails ) > 0 ) {
300
+
301
+ $notification = ES_DB_Mailing_Queue::get_notification_by_hash( $notification_guid );
302
+
303
+ $subject = $this->get_cron_admin_email_subject();
304
+ $content = $this->get_cron_admin_email_content();
305
+
306
+ if ( ! empty( $content ) && isset( $notification['subject'] ) ) {
307
+
308
+ $subject = str_replace( '{{SUBJECT}}', $notification['subject'], $subject );
309
+
310
+ $email_count = $notification['count'];
311
+ $post_subject = $notification['subject'];
312
+ $cron_date = date( 'Y-m-d h:i:s' );
313
+
314
+ $content = str_replace( '{{DATE}}', $cron_date, $content );
315
+ $content = str_replace( '{{COUNT}}', $email_count, $content );
316
+ $content = str_replace( '{{SUBJECT}}', $post_subject, $content );
317
+
318
+ $this->add_unsubscribe_link = false;
319
+ $this->add_tracking_pixel = false;
320
+
321
+ $this->send( $subject, $content, $admin_emails );
322
+ }
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Get cron admin email subject
328
+ *
329
+ * @return mixed|void
330
+ *
331
+ * @since 4.3.2
332
+ */
333
+ public function get_cron_admin_email_subject() {
334
+ return get_option( 'ig_es_cron_admin_email_subject', __( 'Campaign Sent!', 'email-subscribers' ) );
335
+ }
336
+
337
+ /**
338
+ * Get cron admin email content
339
+ *
340
+ * @return mixed|void
341
+ *
342
+ * @since 4.3.2
343
+ */
344
+ public function get_cron_admin_email_content() {
345
+ return wpautop( get_option( 'ig_es_cron_admin_email', '' ) );
346
+ }
347
+
348
+ /**
349
+ * Can send cron admin email?
350
+ *
351
+ * @return bool
352
+ *
353
+ * @since 4.3.2
354
+ */
355
+ public function can_send_cron_admin_email() {
356
+
357
+ $notify_admin = get_option( 'ig_es_enable_cron_admin_email', 'yes' );
358
+
359
+ if ( 'yes' === $notify_admin ) {
360
+ return true;
361
+ }
362
+
363
+ return false;
364
+ }
365
+
366
+ /**
367
+ * Get admin emails
368
+ *
369
+ * @return array
370
+ *
371
+ * @since 4.3.2
372
+ */
373
+ public function get_admin_emails() {
374
+
375
+ $admin_email_addresses = get_option( 'ig_es_admin_emails', '' );
376
+
377
+ return explode( ',', $admin_email_addresses );
378
+ }
379
+
380
+ /**
381
+ * Send Welcome email after subscription
382
+ *
383
+ * @param $email
384
+ * @param $data
385
+ *
386
+ * @since 4.1.13
387
+ */
388
+ public function send_welcome_email( $email, $data = array() ) {
389
+
390
+ if ( $this->can_send_welcome_email() ) {
391
+
392
+ // Prepare Welcome Email Subject
393
+ $subject = $this->get_welcome_email_subject();
394
+
395
+ // Prepare Welcome Email Content
396
+ $content = $this->get_welcome_email_content();
397
+
398
+ // Backward Compatibility...Earlier we used to use {{LINK}} for Unsubscribe link
399
+ $content = str_replace( "{{LINK}}", "{{UNSUBSCRIBE-LINK}}", $content );
400
+
401
+ // Don't add Unsubscribe link. It should be there in content
402
+ $this->add_unsubscribe_link = false;
403
+ $this->add_tracking_pixel = false;
404
+ // Send Email
405
+ $this->send( $subject, $content, $email, $data );
406
+ }
407
+
408
+ }
409
+
410
+ /**
411
+ * Get Welcome Email Subject
412
+ *
413
+ * @return string
414
+ *
415
+ * @since 4.3.2
416
+ */
417
+ public function get_welcome_email_subject() {
418
+ return stripslashes( get_option( 'ig_es_welcome_email_subject', '' ) );
419
+ }
420
+
421
+ /**
422
+ * Get Welcome Email Message
423
+ *
424
+ * @return string
425
+ *
426
+ * @since 4.3.2
427
+ */
428
+ public function get_welcome_email_content() {
429
+ return wpautop( stripslashes( get_option( 'ig_es_welcome_email_content', '' ) ) );
430
+ }
431
+
432
+ /**
433
+ * Enable Welcome Email?
434
+ *
435
+ * @return bool
436
+ *
437
+ * @since 4.3.2
438
+ */
439
+ public function can_send_welcome_email() {
440
+ // Enable Welcome Email?
441
+ $enable_welcome_email = get_option( 'ig_es_enable_welcome_email', 'no' );
442
+
443
+ if ( $enable_welcome_email === 'yes' ) {
444
+ return true;
445
+ }
446
+
447
+ return false;
448
+ }
449
+
450
+ /**
451
+ * Send Test Email
452
+ *
453
+ * @param string $email
454
+ * @param array $merge_tags
455
+ *
456
+ * @return bool
457
+ *
458
+ * @since 4.3.2
459
+ */
460
+ public function send_test_email( $email = '', $subject = '', $content = '', $merge_tags = array() ) {
461
+
462
+ if ( empty( $email ) ) {
463
+ return false;
464
+ }
465
+
466
+ if ( empty( $subject ) ) {
467
+ $subject = $this->get_test_email_subject();
468
+ }
469
+
470
+ if ( empty( $content ) ) {
471
+ $content = $this->get_test_email_content();
472
+ }
473
+
474
+ // Disable
475
+ $this->add_unsubscribe_link = false;
476
+ $this->add_tracking_pixel = false;
477
+
478
+ return $this->send( $subject, $content, $email, $merge_tags );
479
+ }
480
+
481
+ /**
482
+ * Get Test Email Subject
483
+ *
484
+ * @param string $email
485
+ *
486
+ * @return string
487
+ *
488
+ * @since 4.3.2
489
+ */
490
+ public function get_test_email_subject( $email = '' ) {
491
+ return 'Email Subscribers: ' . sprintf( esc_html__( 'Test email to %s', 'email-subscribers' ), $email );
492
+ }
493
+
494
+ /**
495
+ * Get test email content
496
+ *
497
+ * @return false|string
498
+ *
499
+ * @since 4.3.2
500
+ */
501
+ public function get_test_email_content() {
502
+ ob_start();
503
+ ?>
504
+ <html>
505
+ <head></head>
506
+ <body>
507
+ <p>Congrats, test email was sent successfully!</p>
508
+ <p>Thank you for trying out Email Subscribers. We are on a mission to make the best Email Marketing Automation plugin for WordPress.</p>
509
+ <p>If you find this plugin useful, please consider giving us <a href="https://wordpress.org/support/plugin/email-subscribers/reviews/?filter=5">5 stars review</a> on WordPress!</p>
510
+ <p>Nirav Mehta</p>
511
+ <p>Founder, <a href="https://www.icegram.com/">Icegram</a></p>
512
+ </body>
513
+ </html>
514
+
515
+ <?php
516
+ $content = ob_get_clean();
517
+
518
+ return $content;
519
+ }
520
+
521
+ /**
522
+ * Send Email
523
+ *
524
+ * @param $subject
525
+ * @param $content
526
+ * @param array $emails
527
+ * @param array $merge_tags
528
+ * @param bool $nl2br
529
+ *
530
+ * @return mixed
531
+ *
532
+ * @since 4.3.2
533
+ */
534
+ public function send( $subject, $content, $emails = array(), $merge_tags = array(), $nl2br = false ) {
535
+
536
+ ignore_user_abort( true );
537
+
538
+ $this->time_start = time();
539
+ $message_id = ! empty( $merge_tags['message_id'] ) ? $merge_tags['message_id'] : 0;
540
+ $campaign_id = ! empty( $merge_tags['campaign_id'] ) ? $merge_tags['campaign_id'] : 0;
541
+
542
+ $subject = $this->prepare_subject( $subject );
543
+
544
+ $content = $this->prepare_content( $content, $merge_tags, $nl2br );
545
+
546
+ $response = array();
547
+
548
+ if ( is_string( $emails ) ) {
549
+ $emails = array( $emails );
550
+ }
551
+
552
+ $this->email_id_map = ES()->contacts_db->get_email_id_map( (array) $emails );
553
+
554
+ foreach ( (array) $emails as $email ) {
555
+
556
+ // Clean it.
557
+ $email = trim( $email );
558
+
559
+ $response['status'] = 'SUCCESS';
560
+
561
+ // Don't find contact_id?
562
+ $contact_id = ! empty( $this->email_id_map[ $email ] ) ? $this->email_id_map[ $email ] : 0;
563
+
564
+ $merge_tags['contact_id'] = $contact_id;
565
+
566
+ $merge_tags = array_merge( $merge_tags, $this->get_contact_merge_tags( $contact_id ) );
567
+
568
+ $this->link_data = array(
569
+ 'message_id' => $message_id,
570
+ 'campaign_id' => $campaign_id,
571
+ 'contact_id' => $contact_id,
572
+ 'email' => $email,
573
+ 'guid' => ig_es_get_data( $merge_tags, 'hash', '' )
574
+ );
575
+
576
+ do_action( 'ig_es_before_message_send', $contact_id, $campaign_id, $message_id );
577
+
578
+ $message = $this->build_message( $subject, $content, $email, $merge_tags, $nl2br );
579
+
580
+ //object | WP_Error
581
+ $send_response = $this->mailer->send( $message );
582
+
583
+ // Error Sending Email?
584
+ if ( is_wp_error( $send_response ) ) {
585
+ $response['status'] = 'ERROR';
586
+ $response['message'] = $send_response->get_error_messages();
587
+
588
+ //TODO: Log somewhere
589
+ } else {
590
+ // Successfully Sent Email
591
+
592
+ // Track Message Sent
593
+ do_action( 'ig_es_message_sent', $contact_id, $campaign_id, $message_id );
594
+ }
595
+
596
+ // Reduce Email Sending Limit for this hour
597
+ $this->email_limit --;
598
+
599
+ if ( $this->limits_exceeded() ) {
600
+ break;
601
+ }
602
+ }
603
+
604
+ return $response;
605
+
606
+ }
607
+
608
+ /**
609
+ * Prepare ES_Message object
610
+ *
611
+ * @param $subject
612
+ * @param $body
613
+ * @param $email
614
+ * @param array $merge_tags
615
+ *
616
+ * @return ES_Message
617
+ *
618
+ * @since 4.3.2
619
+ */
620
+ public function build_message( $subject, $body, $email, $merge_tags = array(), $nl2br = false ) {
621
+
622
+ $message = new ES_Message();
623
+
624
+ $sender_name = $this->get_from_name();
625
+ $sender_email = $this->get_from_email();
626
+
627
+ $subject = html_entity_decode( $subject, ENT_QUOTES, get_bloginfo( 'charset' ) );
628
+
629
+ $message->from = $sender_email;
630
+ $message->from_name = $sender_name;
631
+ $message->to = $email;
632
+ $message->subject = $subject;
633
+ $message->body = $body;
634
+
635
+ $headers = array(
636
+ "From: \"$sender_name\" <$sender_email>",
637
+ "Return-Path: <" . $sender_email . ">",
638
+ "Reply-To: \"" . $sender_name . "\" <" . $sender_email . ">",
639
+ "Content-Type: text/html; charset=\"" . get_bloginfo( 'charset' ) . "\""
640
+ );
641
+
642
+ $message->headers = $headers;
643
+
644
+ $message->body = preg_replace( '/data-json=".*?"/is', '', $message->body );
645
+ $message->body = preg_replace( '/ +/s', ' ', $message->body );
646
+
647
+ $message->subject = $this->replace_merge_tags( $message->subject, $merge_tags );
648
+
649
+ // Can Track Clicks? Replace Links
650
+ $message->body = $this->replace_links( $message->body );
651
+
652
+ // Unsubscribe Text
653
+ $unsubscribe_message = $this->get_unsubscribe_text();
654
+
655
+ // Can Track Email Open? Add pixel.
656
+ $email_tracking_image = $this->get_tracking_pixel();
657
+
658
+ $message->body = $message->body . $unsubscribe_message . $email_tracking_image;
659
+
660
+ if ( $nl2br ) {
661
+ $message->body = nl2br( $message->body );
662
+ }
663
+
664
+ $message->body = $this->replace_merge_tags( $message->body, $merge_tags );
665
+
666
+ $message->body_text = $this->convert_to_text( $message->body );
667
+
668
+ $campaign_id = ! empty( $merge_tags['campaign_id'] ) ? $merge_tags['campaign_id'] : 0;
669
+
670
+ $message->body = $this->set_pre_header_text( $message->body, $campaign_id );
671
+
672
+ return $message;
673
+ }
674
+
675
+ /**
676
+ * Set Pre header text
677
+ *
678
+ * @param $content
679
+ * @param int $campaign_id
680
+ *
681
+ * @return string
682
+ *
683
+ * @since 4.3.2
684
+ */
685
+ public function set_pre_header_text( $content, $campaign_id = 0 ) {
686
+
687
+ if ( ! empty( $campaign_id ) ) {
688
+
689
+ $meta = ES()->campaigns_db->get_campaign_meta_by_id( $campaign_id );
690
+
691
+ $pre_header_text = ! empty( $meta['pre_header'] ) ? $meta['pre_header'] : '';
692
+
693
+ if ( ! empty( $pre_header_text ) ) {
694
+ $content = '<span class="es_preheader" style="display: none !important; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;">' . $pre_header_text . '</span>' . $content;
695
+ }
696
+ }
697
+
698
+ return $content;
699
+ }
700
+
701
+ /**
702
+ * Prepare Subject
703
+ *
704
+ * @param $subject
705
+ *
706
+ * @return mixed
707
+ *
708
+ * @since 4.3.2
709
+ */
710
+ public function prepare_subject( $subject ) {
711
+ return $subject;
712
+ }
713
+
714
+ /**
715
+ * Prepare Content
716
+ *
717
+ * @param $content
718
+ *
719
+ * @return string|string[]|null
720
+ *
721
+ * @since 4.3.2
722
+ */
723
+ public function prepare_content( $content, $merge_tags = array(), $nl2br = false ) {
724
+ // Convert text equivalent of smilies to images.
725
+ $content = convert_chars( convert_smilies( wptexturize( $content ) ) );
726
+
727
+ if ( isset( $GLOBALS['wp_embed'] ) ) {
728
+ $content = $GLOBALS['wp_embed']->autoembed( $content );
729
+ }
730
+
731
+ // Replaces double line-breaks with paragraph elements.
732
+ //$content = wpautop( $content );
733
+
734
+ // Have shortcode? Execute it.
735
+ $content = do_shortcode( shortcode_unautop( $content ) );
736
+
737
+ // Format Templates.
738
+ $data['content'] = $content;
739
+ $campaign_id = ! empty( $merge_tags['campaign_id'] ) ? $merge_tags['campaign_id'] : 0;
740
+ $data['tmpl_id'] = ! empty( $campaign_id ) ? ES()->campaigns_db->get_template_id_by_campaign( $campaign_id ) : 0;
741
+ $data['campaign_id'] = $campaign_id;
742
+
743
+ $data = apply_filters( 'es_after_process_template_body', $data );
744
+
745
+ $content = $data['content'];
746
+
747
+ return $content;
748
+ }
749
+
750
+ public function get_contact_merge_tags( $contact_id = 0 ) {
751
+ $merge_tags = array();
752
+
753
+ if ( 0 != $contact_id ) {
754
+ $contact_details = ES()->contacts_db->get_details_by_ids( array( $contact_id ) );
755
+ if ( is_array( $contact_details ) ) {
756
+ $contact_details = array_shift( $contact_details );
757
+
758
+ $first_name = $contact_details['first_name'];
759
+ $last_name = $contact_details['last_name'];
760
+
761
+ $merge_tags['first_name'] = $first_name;
762
+ $merge_tags['last_name'] = $last_name;
763
+ $merge_tags['name'] = ES_Common::prepare_name_from_first_name_last_name( $first_name, $last_name );
764
+ $merge_tags['hash'] = $contact_details['hash'];
765
+ $merge_tags['email'] = $contact_details['email'];
766
+ }
767
+ }
768
+
769
+ return $merge_tags;
770
+ }
771
+
772
+ /**
773
+ * Replace Merge Tags
774
+ *
775
+ * @param string $content
776
+ * @param array $merge_tags
777
+ *
778
+ * @return mixed|string
779
+ *
780
+ * @since 4.3.2
781
+ */
782
+ public function replace_merge_tags( $content = '', $merge_tags = array() ) {
783
+
784
+ $blog_name = get_option( 'blogname' );
785
+ $total_contacts = ES()->contacts_db->get_total_contacts();
786
+ $site_url = home_url( '/' );
787
+
788
+ $contact_id = ig_es_get_data( $merge_tags, 'contact_id', 0 );
789
+
790
+ $name = ig_es_get_data( $merge_tags, 'name', '' );
791
+ $email = ig_es_get_data( $merge_tags, 'email', '' );
792
+ $first_name = ig_es_get_data( $merge_tags, 'first_name', '' );
793
+ $last_name = ig_es_get_data( $merge_tags, 'last_name', '' );
794
+ $hash = ig_es_get_data( $merge_tags, 'hash', '' );
795
+ $list_name = ig_es_get_data( $merge_tags, 'list_name', '' );
796
+ $campaign_id = ig_es_get_data( $merge_tags, 'campaign_id', 0 );
797
+ $message_id = ig_es_get_data( $merge_tags, 'message_id', 0 );
798
+
799
+ $link_data = array(
800
+ 'message_id' => $message_id,
801
+ 'campaign_id' => $campaign_id,
802
+ 'contact_id' => $contact_id,
803
+ 'email' => $email,
804
+ 'guid' => $hash
805
+ );
806
+
807
+ $this->link_data = $link_data;
808
+
809
+ $subscribe_link = $this->get_subscribe_link( $link_data );
810
+ $unsubscribe_link = $this->get_unsubscribe_link( $link_data );
811
+
812
+ $content = str_replace( "{{NAME}}", $name, $content );
813
+ $content = str_replace( "{{FIRSTNAME}}", $first_name, $content );
814
+ $content = str_replace( "{{LASTNAME}}", $last_name, $content );
815
+ $content = str_replace( "{{EMAIL}}", $email, $content );
816
+
817
+ // TODO: This is a quick workaround to handle <a href="{{LINK}}?utm_source=abc" >
818
+ // TODO: Implement some good solution
819
+
820
+ $content = str_replace( "{{LINK}}?", "{{LINK}}&", $content );
821
+ $content = str_replace( "{{LINK}}", $subscribe_link, $content );
822
+
823
+ $content = str_replace( "{{SUBSCRIBE-LINK}}?", "{{SUBSCRIBE-LINK}}&", $content );
824
+ $content = str_replace( "{{SUBSCRIBE-LINK}}", $subscribe_link, $content );
825
+
826
+ $content = str_replace( "{{UNSUBSCRIBE-LINK}}?", "{{UNSUBSCRIBE-LINK}}&", $content );
827
+ $content = str_replace( "{{UNSUBSCRIBE-LINK}}", $unsubscribe_link, $content );
828
+
829
+ $content = str_replace( "{{TOTAL-CONTACTS}}", $total_contacts, $content );
830
+ $content = str_replace( "{{GROUP}}", $list_name, $content );
831
+ $content = str_replace( "{{LIST}}", $list_name, $content );
832
+ $content = str_replace( "{{SITENAME}}", $blog_name, $content );
833
+ $content = str_replace( "{{SITEURL}}", $site_url, $content );
834
+
835
+ return $content;
836
+ }
837
+
838
+ /**
839
+ * @param $html
840
+ * @param bool $links_only
841
+ *
842
+ * @return mixed|string|string[]|null
843
+ *
844
+ * @since 4.0.0
845
+ * @since 4.3.2
846
+ */
847
+ public function convert_to_text( $html, $links_only = false ) {
848
+
849
+ if ( $links_only ) {
850
+ $links = '/< *a[^>]*href *= *"([^#]*)"[^>]*>(.*)< *\/ *a *>/Uis';
851
+ $text = preg_replace( $links, '${2} [${1}]', $html );
852
+ $text = str_replace( array( ' ', '&nbsp;' ), ' ', strip_tags( $text ) );
853
+ $text = @html_entity_decode( $text, ENT_QUOTES, 'UTF-8' );
854
+
855
+ return trim( $text );
856
+
857
+ } else {
858
+ require_once ES_PLUGIN_DIR . 'lite/includes/libraries/class-es-html2text.php';
859
+ $htmlconverter = new ES_Html2Text( $html, array( 'width' => 200, 'do_links' => 'table' ) );
860
+
861
+ $text = trim( $htmlconverter->get_text() );
862
+ $text = preg_replace( '/\s*$^\s*/mu', "\n\n", $text );
863
+ $text = preg_replace( '/[ \t]+/u', ' ', $text );
864
+
865
+ return $text;
866
+
867
+ }
868
+ }
869
+
870
+ /**
871
+ * Replace links with tracking link
872
+ *
873
+ * @param $content
874
+ * @param $data
875
+ *
876
+ * @return string|string[]|null
877
+ *
878
+ * @since 4.2.4
879
+ * @since 4.3.2
880
+ */
881
+ public function replace_links( $content = '', $link_data = array() ) {
882
+
883
+ if ( $this->can_track_clicks() ) {
884
+
885
+ if ( empty( $link_data ) ) {
886
+ $link_data = $this->link_data;
887
+ }
888
+
889
+ $link_data['action'] = 'click';
890
+
891
+ // get all links from the basecontent
892
+ preg_match_all( '# href=(\'|")?(https?[^\'"]+)(\'|")?#', $content, $links );
893
+ $links = $links[2];
894
+
895
+ if ( empty( $links ) ) {
896
+ return $content;
897
+ }
898
+
899
+ $inserted_links = array();
900
+
901
+ $campaign_id = ! empty( $data['campaign_id'] ) ? $data['campaign_id'] : 0;
902
+ $message_id = ! empty( $data['message_id'] ) ? $data['message_id'] : 0;
903
+
904
+ foreach ( $links as $link ) {
905
+
906
+ if ( ! isset( $inserted_links[ $link ] ) ) {
907
+ $index = 0;
908
+ } else {
909
+ $index = $inserted_links[ $link ] + 1;
910
+ }
911
+
912
+ $inserted_links[ $link ] = $index;
913
+ $result = ES()->links_db->get_link_by_campaign_id( $link, $campaign_id, $message_id, $index );
914
+
915
+ if ( is_array( $result ) && count( $result ) > 0 ) {
916
+ $hash = $result[0]['hash'];
917
+ } else {
918
+
919
+ $hash = ES_Common::generate_hash( 12 );
920
+
921
+ $link_data = array(
922
+ 'link' => $link,
923
+ 'message_id' => $message_id,
924
+ 'campaign_id' => $campaign_id,
925
+ 'hash' => $hash,
926
+ 'i' => $index
927
+ );
928
+
929
+ ES()->links_db->insert( $link_data );
930
+ }
931
+
932
+ $data['link_hash'] = $hash;
933
+
934
+ $new_link = $this->prepare_link( $data );
935
+
936
+ $link = ' href="' . $link . '"';
937
+ $new_link = ' href="' . $new_link . '"';
938
+
939
+ if ( ( $pos = strpos( $content, $link ) ) !== false ) {
940
+ $content = preg_replace( '/' . preg_quote( $link, '/' ) . '/', $new_link, $content, 1 );
941
+ }
942
+ }
943
+ }
944
+
945
+ return $content;
946
+ }
947
+
948
+ /**
949
+ * Get Sender Name
950
+ *
951
+ * @return mixed|string|void
952
+ *
953
+ * @since 4.3.2
954
+ */
955
+ public function get_from_name() {
956
+
957
+ $site_title = get_bloginfo();
958
+
959
+ $from_name = get_option( 'ig_es_from_name', '' );
960
+
961
+ $from_name = ! empty( $from_name ) ? $from_name : $site_title;
962
+
963
+ return $from_name;
964
+ }
965
+
966
+ /**
967
+ * Get Sender Email
968
+ *
969
+ * @return mixed|void
970
+ *
971
+ * @since 4.3.2
972
+ */
973
+ public function get_from_email() {
974
+
975
+ $admin_email = get_option( 'admin_email', '' );
976
+
977
+ $from_email = get_option( 'ig_es_from_email', '' );
978
+
979
+ $from_email = ! empty( $from_email ) ? $from_email : $admin_email;
980
+
981
+ return $from_email;
982
+ }
983
+
984
+ /**
985
+ * Allow click tracking?
986
+ *
987
+ * @param int $contact_id
988
+ * @param int $campaign_id
989
+ *
990
+ * @return mixed|void
991
+ *
992
+ * @since 4.3.2
993
+ */
994
+ public function can_track_clicks( $contact_id = 0, $campaign_id = 0 ) {
995
+ $is_track_clicks = false;
996
+
997
+ return apply_filters( 'ig_es_track_clicks', $is_track_clicks, $contact_id, $campaign_id );
998
+ }
999
+
1000
+ /**
1001
+ * Allow tracking email open?
1002
+ *
1003
+ * @param int $contact_id
1004
+ * @param int $campaign_id
1005
+ *
1006
+ * @return bool
1007
+ *
1008
+ * @since 4.3.2
1009
+ */
1010
+ public function can_track_open( $contact_id = 0, $campaign_id = 0 ) {
1011
+
1012
+ if ( $this->add_tracking_pixel ) {
1013
+
1014
+ $is_track_email_opens = get_option( 'ig_es_track_email_opens', 'yes' );
1015
+
1016
+ $is_track_email_opens = apply_filters( 'ig_es_track_open', $is_track_email_opens, $contact_id, $campaign_id );
1017
+
1018
+ if ( 'yes' === $is_track_email_opens ) {
1019
+ return true;
1020
+ }
1021
+ }
1022
+
1023
+ return false;
1024
+ }
1025
+
1026
+ /**
1027
+ * Get Tracking pixel
1028
+ *
1029
+ * @param array $data
1030
+ *
1031
+ * @return string
1032
+ *
1033
+ * @since 4.2.0
1034
+ */
1035
+ public function get_tracking_pixel( $link_data = array() ) {
1036
+
1037
+ $tracking_image = '';
1038
+
1039
+ if ( $this->can_track_open() ) {
1040
+
1041
+ if ( empty( $link_data ) ) {
1042
+ $link_data = $this->link_data;
1043
+ }
1044
+
1045
+ $link_data['action'] = 'open';
1046
+
1047
+ $url = $this->prepare_link( $link_data );
1048
+
1049
+ $tracking_image = "<img src='{$url}' width='1' height='1' alt=''/>";
1050
+ }
1051
+
1052
+ return $tracking_image;
1053
+ }
1054
+
1055
+ /**
1056
+ * Get link
1057
+ *
1058
+ * @param array $data
1059
+ *
1060
+ * @return string
1061
+ *
1062
+ * @since 4.0.0
1063
+ * @since 4.2.0
1064
+ * @since 4.3.2
1065
+ */
1066
+ public function prepare_link( $data = array() ) {
1067
+ /**
1068
+ * We are getting different data like action, message_id, campaign_id, contact_id, guid, email etc in $data
1069
+ */
1070
+ $action = ! empty( $data['action'] ) ? $data['action'] : '';
1071
+
1072
+ if ( 'subscribe' === $action ) {
1073
+ $action = 'optin';
1074
+ }
1075
+
1076
+ $link = add_query_arg( 'es', $action, site_url( '/' ) );
1077
+
1078
+ $data = ig_es_encode_request_data( $data );
1079
+
1080
+ $link = add_query_arg( 'hash', $data, $link );
1081
+
1082
+ return $link;
1083
+ }
1084
+
1085
+ /**
1086
+ * Get Unsubscribe text
1087
+ *
1088
+ * @param $link_data
1089
+ *
1090
+ * @return mixed|string|void
1091
+ *
1092
+ * @since 4.3.2
1093
+ */
1094
+ public function get_unsubscribe_text( $link_data = array() ) {
1095
+
1096
+ $text = '';
1097
+
1098
+ if ( $this->add_unsubscribe_link ) {
1099
+
1100
+ if ( empty( $link_data ) ) {
1101
+ $link_data = $this->link_data;
1102
+ }
1103
+
1104
+ $unsubscribe_link = $this->get_unsubscribe_link( $link_data );
1105
+
1106
+ $text = get_option( 'ig_es_unsubscribe_link_content', '' );
1107
+
1108
+ $text = stripslashes( $text );
1109
+ $text = str_replace( "{{LINK}}", "{{UNSUBSCRIBE-LINK}}", $text );
1110
+ $text = str_replace( "{{UNSUBSCRIBE-LINK}}", $unsubscribe_link, $text );
1111
+ }
1112
+
1113
+ return $text;
1114
+ }
1115
+
1116
+ /**
1117
+ * Get Unsubscribe link
1118
+ *
1119
+ * @param $link_data
1120
+ *
1121
+ * @return string
1122
+ *
1123
+ * @since 4.3.2
1124
+ */
1125
+ public function get_unsubscribe_link( $link_data = array() ) {
1126
+ $link_data['action'] = 'unsubscribe';
1127
+
1128
+ return $this->prepare_link( $link_data );
1129
+ }
1130
+
1131
+ /**
1132
+ * Get Subscribe link
1133
+ *
1134
+ * @param $link_data
1135
+ *
1136
+ * @return string
1137
+ *
1138
+ * @since 4.3.2
1139
+ */
1140
+ public function get_subscribe_link( $link_data ) {
1141
+ $link_data['action'] = 'subscribe';
1142
+
1143
+ return $this->prepare_link( $link_data );
1144
+ }
1145
+ }
1146
+ }
lite/includes/classes/class-es-message.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ if ( ! class_exists( 'ES_Message' ) ) {
8
+ /**
9
+ * Class ES_Message
10
+ *
11
+ * @since 4.3.2
12
+ */
13
+ class ES_Message {
14
+ /**
15
+ * @var string
16
+ *
17
+ * @since 4.3.2
18
+ */
19
+ var $to = '';
20
+
21
+ /**
22
+ * @var string
23
+ *
24
+ * @since 4.3.2
25
+ */
26
+ var $to_name = '';
27
+
28
+ /**
29
+ * @var array
30
+ *
31
+ * @since 4.3.2
32
+ */
33
+ var $headers = array();
34
+
35
+ /**
36
+ * @var string
37
+ *
38
+ * @since 4.3.2
39
+ */
40
+ var $error = '';
41
+
42
+ /**
43
+ * @var string
44
+ *
45
+ * @since 4.3.2
46
+ */
47
+ var $subject = '';
48
+
49
+ /**
50
+ * @var string
51
+ *
52
+ * @since 4.3.2
53
+ */
54
+ var $body = '';
55
+
56
+ /**
57
+ * @var string
58
+ *
59
+ * @since 4.3.2
60
+ */
61
+ var $body_text = '';
62
+
63
+ /**
64
+ * @var
65
+ *
66
+ * @sinc 4.3.2
67
+ */
68
+ var $from;
69
+
70
+ /**
71
+ * @var string
72
+ *
73
+ * @since 4.3.2
74
+ */
75
+ var $from_name = '';
76
+
77
+
78
+ public function __construct() {
79
+
80
+ }
81
+
82
+ }
83
+ }
84
+
85
+
lite/includes/classes/class-es-newsletters.php ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * The admin-specific functionality of the plugin.
10
+ *
11
+ * Admin Settings
12
+ *
13
+ * @package Email_Subscribers
14
+ * @subpackage Email_Subscribers/admin
15
+ * @author Your Name <email@example.com>
16
+ */
17
+ class ES_Newsletters {
18
+
19
+ // class instance
20
+ static $instance;
21
+
22
+ // class constructor
23
+ public function __construct() {
24
+ add_filter( 'ig_es_refresh_newsletter_content', array( $this, 'refresh_newsletter_content' ), 10, 2 );
25
+ }
26
+
27
+ public static function set_screen( $status, $option, $value ) {
28
+ return $value;
29
+ }
30
+
31
+ public function es_newsletters_settings_callback() {
32
+
33
+
34
+ $submitted = ig_es_get_request_data( 'submitted' );
35
+ $preview = ig_es_get_request_data( 'es_broadcast_preview' );
36
+ $broadcast_data = ig_es_get_request_data( 'broadcast_data', array(), false );
37
+ if( 'preview' !== $preview ){
38
+ if ( 'submitted' === $submitted ) {
39
+
40
+ // $email_sent_type = __('Active', 'email-subscribers');
41
+ $list_id = !empty($broadcast_data['list_ids']) ? $broadcast_data['list_ids'] : '' ;
42
+ $template_id = !empty($broadcast_data['template_id']) ? $broadcast_data['template_id'] : '' ;
43
+ $subject = !empty($broadcast_data['subject']) ? $broadcast_data['subject'] : '' ;
44
+ // $template_id = ig_es_get_request_data( 'ig_es_broadcast_base_template_id' );
45
+ if ( empty( $broadcast_data['body']) ) {
46
+ // if ( empty( $template_id) ) {
47
+ $message = __( 'Please add message body or select template', 'email-subscribers' );
48
+ ES_Common::show_message( $message, 'error' );
49
+ } elseif ( empty( $list_id ) ) {
50
+ $message = __( 'Please select list.', 'email-subscribers' );
51
+ ES_Common::show_message( $message, 'error' );
52
+ } elseif ( empty( $subject ) ) {
53
+ $message = __( 'Please add the subject', 'email-subscribers' );
54
+ ES_Common::show_message( $message, 'error' );
55
+ }else {
56
+ $broadcast_data['base_template_id'] = $template_id;
57
+ $broadcast_data['list_ids'] = $list_id;
58
+ $broadcast_data['status'] = 1;
59
+ $meta = !empty($broadcast_data['meta']) ? $broadcast_data['meta'] : array();
60
+ $meta['pre_header'] = $broadcast_data['pre_header'];
61
+ $broadcast_data['meta'] = maybe_serialize($meta);
62
+ self::es_send_email_callback( $broadcast_data );
63
+
64
+ $reports_url = admin_url( 'admin.php?page=es_reports' );
65
+ $message = __( sprintf( 'A new broadcast has been created successfully! Contacts from selected list will be notified within an hour. Want to notify now? <a href="%s" target="_blank">Click here</a>', $reports_url ), 'email-subscribers' );
66
+
67
+ ES_Common::show_message( $message, 'success' );
68
+
69
+ do_action( 'ig_es_broadcast_created' );
70
+ $broadcast_data = array();
71
+ }
72
+
73
+ }
74
+
75
+ $this->prepare_newsletter_settings_form();
76
+ }else if('preview' === $preview ){
77
+ // $broadcast_data = ig_es_get_request_data( 'broadcast_data', array(), false );
78
+ if ( empty( $broadcast_data['body'] ) ) {
79
+ $message = __( 'Please add message content', 'email-subscribers' );
80
+ ES_Common::show_message( $message, 'error' );
81
+ $this->prepare_newsletter_settings_form();
82
+ } else{
83
+ //content validation
84
+ $template_data['content'] = !empty($broadcast_data['body']) ? $broadcast_data['body'] : '';
85
+ $template_data['template_id'] = !empty($broadcast_data['template_id']) ? $broadcast_data['template_id'] : '';
86
+ $this->es_broadcast_preview_callback( $template_data );
87
+
88
+ }
89
+
90
+ }
91
+ }
92
+
93
+ public function prepare_newsletter_settings_form() {
94
+ $newsletter_data = array();
95
+ $templates = ES_Common::prepare_templates_dropdown_options( 'newsletter' );
96
+ $lists = ES_Common::prepare_list_dropdown_options();
97
+ $from_email = ES_Common::get_ig_option( 'from_email' );
98
+
99
+ ?>
100
+
101
+ <div class="wrap">
102
+ <h2 class="wp-heading-inline"><?php _e( 'Campaigns > Broadcast', 'email-subscribers' ); ?>
103
+ <a href="admin.php?page=es_campaigns" class="page-title-action"><?php _e( 'Campaigns', 'email-subscribers' ) ?></a>
104
+ <a href="edit.php?post_type=es_template" class="page-title-action es-imp-button"><?php _e( 'Manage Templates', 'email-subscribers' ) ?></a>
105
+ </h2>
106
+ <div class="es-form" style="width: 100%;">
107
+ <form method="post" action="#">
108
+ <div class="es_newsletters_settings_wrapper">
109
+ <div class="es_campaign_name_wrapper ">
110
+ <input placeholder="Add Broadcast name" type="text" class="es_newsletter_name" name="broadcast_data[name]" value="">
111
+ <input id="ig_es_campaign_submit_button" class="es_primary_btn" type="submit" name="submit" value="Send Broadcast">
112
+ <input type="hidden" name="submitted" value="submitted">
113
+ </div>
114
+ <div class="es_settings_left_pan">
115
+ <div class="es_settings_field">
116
+ <label><?php _e('From Email', 'email-subscribers')?><br/><input type="email" name="broadcast_data[from_email]" value="<?php echo $from_email; ?>"/></label>
117
+ </div>
118
+ <div class="es_settings_field">
119
+ <label><?php _e('Design template', 'email-subscribers')?><br/><select name="broadcast_data[template_id]" id="base_template_id"><?php echo $templates ?></select></label>
120
+ </div>
121
+ <div class="es_settings_field"><label><?php _e('Subject', 'email-subscribers')?><br/><input type="text" id="ig_es_broadcast_subject" name="broadcast_data[subject]" placeholder="<?php _e('New Broadcast', 'email-subscribers')?>"/></label></div>
122
+ <div class="es_settings_field"><label><?php _e('Pre Header', 'email-subscribers')?><br/><input placeholder="<?php _e('Add Pre header', 'email-subscribers');?>"type="text" name="broadcast_data[pre_header]"/></label></div>
123
+ <div class="es_settings_field">
124
+ <label><?php _e('Body', 'email-subscribers'); ?></label>
125
+ <?php
126
+ $body = !empty($broadcast_data['body']) ? $broadcast_data['body'] : '';
127
+ $editor_args = array(
128
+ 'textarea_name' => 'broadcast_data[body]',
129
+ 'textarea_rows' => 40,
130
+ 'editor_class' => 'wp-editor-content',
131
+ 'media_buttons' => true,
132
+ 'tinymce' => true,
133
+ 'quicktags'=> true,
134
+ 'editor_class' => 'wp-editor-boradcast'
135
+ );
136
+ wp_editor( $body, 'edit-es-boradcast-body', $editor_args ); ?>
137
+ </div>
138
+ <?php do_action( 'ig_es_after_broadcast_left_pan_settings'); ?>
139
+ </div>
140
+ <div class="es_settings_right_pan">
141
+ <div class="es_settings_field">
142
+ <label><?php _e('Recipients', 'email-subscribers')?><br/><select name="broadcast_data[list_ids]" id="ig_es_broadcast_list_ids"><?php echo $lists ?></select></label>
143
+ </div>
144
+ <hr>
145
+ <div class="es_settings_field">
146
+ <label>
147
+ <input class="es_secondary_btn" type="submit" id="ig_es_preview_broadcast" value="<?php _e('Preview this email in browser', 'email-subscribers')?>">
148
+ <input type="hidden" name="es_broadcast_preview" id="es_broadcast_preview">
149
+ </label>
150
+ </div>
151
+ <?php do_action( 'ig_es_after_broadcast_right_pan_settings'); ?>
152
+ </div>
153
+
154
+ </div>
155
+ </form>
156
+ </div>
157
+ <div clas="es-preview" style="float: right;width: 19%;">
158
+ <div class="es-templ-img"></div>
159
+ </div>
160
+ </div>
161
+
162
+ <?php
163
+
164
+
165
+ }
166
+
167
+ public static function es_send_email_callback( $data ) {
168
+
169
+ $list_id = ! empty( $data['list_ids'] ) ? $data['list_ids'] : '';
170
+
171
+ $title = get_the_title( $data['base_template_id'] );
172
+
173
+ $data['type'] = 'newsletter';
174
+ $data['name'] = !empty( $data['name'] ) ? $data['name'] : $data['subject'] ;
175
+ $data['slug'] = sanitize_title( sanitize_text_field( $data['name'] ) );
176
+
177
+ $data = apply_filters( 'ig_es_broadcast_data', $data );
178
+
179
+ if ( ! empty( $data['body'] ) ) {
180
+
181
+ $campaign_id = ES()->campaigns_db->save_campaign( $data );
182
+
183
+ $data['body'] = ES_Common::es_process_template_body( $data['body'], $data['base_template_id'], $campaign_id );
184
+
185
+ $subscribers = ES()->contacts_db->get_active_contacts_by_list_id( $list_id );
186
+
187
+ if ( ! empty( $subscribers ) && count( $subscribers ) > 0 ) {
188
+ $guid = ES_Common::generate_guid( 6 );
189
+ $data = array(
190
+ 'hash' => $guid,
191
+ 'campaign_id' => $campaign_id,
192
+ 'subject' => $data['subject'],
193
+ 'body' => $data['body'],
194
+ 'count' => count( $subscribers ),
195
+ 'status' => 'In Queue',
196
+ 'start_at' => ! empty( $data['start_at'] ) ? $data['start_at'] : '',
197
+ 'finish_at' => '',
198
+ 'created_at' => ig_get_current_date_time(),
199
+ 'updated_at' => ig_get_current_date_time(),
200
+ 'meta' => maybe_serialize( array( 'type' => 'newsletter' ) )
201
+ );
202
+
203
+ $last_report_id = ES_DB_Mailing_Queue::add_notification( $data );
204
+
205
+ $delivery_data = array();
206
+ $delivery_data['hash'] = $guid;
207
+ $delivery_data['subscribers'] = $subscribers;
208
+ $delivery_data['campaign_id'] = $campaign_id;
209
+ $delivery_data['mailing_queue_id'] = $last_report_id;
210
+ ES_DB_Sending_Queue::do_batch_insert( $delivery_data );
211
+ }
212
+ }
213
+
214
+ return;
215
+
216
+ }
217
+
218
+ public static function refresh_newsletter_content( $content, $args) {
219
+ $campaign_id = $args['campaign_id'];
220
+ $template_id = ES()->campaigns_db->get_template_id_by_campaign( $campaign_id );
221
+ $content['subject'] = ES()->campaigns_db->get_column( 'subject', $campaign_id );
222
+ $content['body'] = ES()->campaigns_db->get_column( 'body', $campaign_id );
223
+ $content['body'] = ES_Common::es_process_template_body( $content['body'], $template_id, $campaign_id );
224
+ return $content;
225
+ }
226
+
227
+ public static function get_instance() {
228
+ if ( ! isset( self::$instance ) ) {
229
+ self::$instance = new self();
230
+ }
231
+
232
+ return self::$instance;
233
+ }
234
+
235
+ public function es_broadcast_preview_callback( $template_data ) {
236
+
237
+ $template_id = $template_data['template_id'];
238
+ if ( !empty($template_data['content'] )) {
239
+ $current_user = wp_get_current_user();
240
+ $username = $current_user->user_login;
241
+ $useremail = $current_user->user_email;
242
+
243
+ $es_template_body = $template_data['content'] ;
244
+
245
+ $es_template_body = ES_Common::es_process_template_body( $es_template_body , $template_id );
246
+ $es_template_body = str_replace( '{{NAME}}', $username, $es_template_body );
247
+ $es_template_body = str_replace( '{{EMAIL}}', $useremail, $es_template_body );
248
+
249
+ if ( has_post_thumbnail( $template_id ) ) {
250
+ $image_array = wp_get_attachment_image_src( get_post_thumbnail_id( $template_id ), 'full' );
251
+ $image = '<img src="' . $image_array[0] . '" class="img-responsive" alt="Image for Post ' . $template_id . '" />';
252
+ } else {
253
+ $image = '';
254
+ }
255
+
256
+ $html = '';
257
+ $html .= '<style type="text/css">
258
+ .es-sidebar {
259
+ width: 23%;
260
+ background-color: rgb(230, 230, 230);
261
+ padding:15px;
262
+ border-right: 1px solid #bdbdbd;
263
+ }
264
+ .es-preview {
265
+ float: left;
266
+ padding:15px;
267
+ width: 70%;
268
+ background-color:#FFF;
269
+ font-size:16px;
270
+ }
271
+ </style>
272
+ <div class="wrap">
273
+ <div class="tool-box">
274
+ <div class="es-main" style="display:flex;">
275
+ <div class="es-sidebar">
276
+ <h2 style="margin-bottom:1em;">
277
+ Template Preview <a class="add-new-h2" target="_blank" href="' . admin_url() . 'admin.php?page=es-general-information">Help</a>
278
+ </h2>
279
+ <p>
280
+ This is how your email may look.<br><br>Note: Different email services (like gmail, yahoo etc) display email content differently. So there could be a slight variation on how your customer will view the email content. </p>
281
+ </div>
282
+ <div class="es-preview">' . $es_template_body . '</div>
283
+ <div style="clear:both;"></div>
284
+ </div>
285
+ <div style="clear:both;"></div>
286
+ </div>
287
+ </div>';
288
+ echo apply_filters( 'the_content', $html );
289
+ } else {
290
+ echo 'Please publish it or save it as a draft';
291
+ }
292
+
293
+ }
294
+
295
+
296
+ }
lite/includes/classes/class-es-old-widget.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ class ES_Old_Widget extends WP_Widget {
9
+
10
+ function __construct() {
11
+ $widget_ops = array( 'classname' => 'widget_text elp-widget', 'description' => __( 'Email Subscribers', 'email-subscribers' ) );
12
+ parent::__construct( 'email-subscribers', __( 'Email Subscribers', 'email-subscribers' ), $widget_ops );
13
+ }
14
+
15
+ function widget( $args, $instance ) {
16
+
17
+ $title = apply_filters( 'widget_title', $instance['es_title'] );
18
+
19
+ echo $args['before_widget'];
20
+
21
+ if ( ! empty( $title ) ) {
22
+ echo $args['before_title'] . $title . $args['after_title'];
23
+ }
24
+
25
+ $display_name = isset( $instance['es_name'] ) ? esc_attr( $instance['es_name'] ) : '';
26
+ $subscribers_group = isset( $instance['es_group'] ) ? esc_attr( $instance['es_group'] ) : '';
27
+ $desc = isset( $instance['es_desc'] ) ? esc_attr( $instance['es_desc'] ) : '';
28
+
29
+ $name = strtolower( $display_name ) != 'no' ? 'yes' : '';
30
+
31
+ $list = ES()->lists_db->get_list_by_name($subscribers_group);
32
+ if(!empty($list)) {
33
+ $list_id = $list['id'];
34
+ }
35
+
36
+ $data['name_visible'] = $name;
37
+ $data['list_visible'] = 'no';
38
+ $data['lists'] = array();
39
+ $data['form_id'] = 0;
40
+ $data['list'] = $list_id;
41
+ $data['desc'] = $desc;
42
+
43
+ ES_Shortcode::render_form( $data );
44
+
45
+ echo $args['after_widget'];
46
+ }
47
+
48
+ function update( $new_instance, $old_instance ) {
49
+ $instance = $old_instance;
50
+ $instance['es_title'] = ( ! empty( $new_instance['es_title'] ) ) ? strip_tags( $new_instance['es_title'] ) : '';
51
+ $instance['es_desc'] = ( ! empty( $new_instance['es_desc'] ) ) ? strip_tags( $new_instance['es_desc'] ) : '';
52
+ $instance['es_name'] = ( ! empty( $new_instance['es_name'] ) ) ? strip_tags( $new_instance['es_name'] ) : '';
53
+ $instance['es_group'] = ( ! empty( $new_instance['es_group'] ) ) ? strip_tags( $new_instance['es_group'] ) : '';
54
+
55
+ return $instance;
56
+ }
57
+
58
+ function form( $instance ) {
59
+ $defaults = array(
60
+ 'es_title' => '',
61
+ 'es_desc' => '',
62
+ 'es_name' => '',
63
+ 'es_group' => ''
64
+ );
65
+ $instance = wp_parse_args( (array) $instance, $defaults );
66
+ $es_title = $instance['es_title'];
67
+ $es_desc = $instance['es_desc'];
68
+ $es_name = $instance['es_name'];
69
+ $es_group = $instance['es_group'];
70
+ ?>
71
+ <p>
72
+ <label for="<?php echo $this->get_field_id( 'es_title' ); ?>"><?php echo __( 'Widget Title', 'email-subscribers' ); ?></label>
73
+ <input class="widefat" id="<?php echo $this->get_field_id( 'es_title' ); ?>" name="<?php echo $this->get_field_name( 'es_title' ); ?>" type="text" value="<?php echo $es_title; ?>"/>
74
+ </p>
75
+ <p>
76
+ <label for="<?php echo $this->get_field_id( 'es_desc' ); ?>"><?php echo __( 'Short description about subscription form', 'email-subscribers' ); ?></label>
77
+ <input class="widefat" id="<?php echo $this->get_field_id( 'es_desc' ); ?>" name="<?php echo $this->get_field_name( 'es_desc' ); ?>" type="text" value="<?php echo $es_desc; ?>"/>
78
+ </p>
79
+ <p>
80
+ <label for="<?php echo $this->get_field_id( 'es_name' ); ?>"><?php echo __( 'Display Name Field', 'email-subscribers' ); ?></label>
81
+ <select class="widefat" id="<?php echo $this->get_field_id( 'es_name' ); ?>" name="<?php echo $this->get_field_name( 'es_name' ); ?>">
82
+ <option value="YES" <?php $this->es_selected( $es_name == 'YES' ); ?>><?php echo __( 'YES', 'email-subscribers' ); ?></option>
83
+ <option value="NO" <?php $this->es_selected( $es_name == 'NO' ); ?>><?php echo __( 'NO', 'email-subscribers' ); ?></option>
84
+ </select>
85
+ </p>
86
+ <p>
87
+ <label for="<?php echo $this->get_field_id( 'es_group' ); ?>"><?php echo __( 'Subscriber Group', 'email-subscribers' ); ?></label>
88
+ <select class="widefat" name="<?php echo $this->get_field_name( 'es_group' ); ?>" id="<?php echo $this->get_field_id( 'es_group' ); ?>">
89
+ <?php
90
+ $groups = ES()->lists_db->get_list_id_name_map();
91
+ if ( count( $groups ) > 0 ) {
92
+ $i = 1;
93
+ foreach ( $groups as $group ) {
94
+ ?>
95
+ <option value="<?php echo esc_html( stripslashes( $group ) ); ?>" <?php if ( stripslashes( $es_group ) == $group ) {
96
+ echo 'selected="selected"';
97
+ } ?>>
98
+ <?php echo stripslashes( $group ); ?>
99
+ </option>
100
+ <?php
101
+ }
102
+ }
103
+ ?>
104
+ </select>
105
+ </p>
106
+ <?php
107
+ }
108
+
109
+ function es_selected( $var ) {
110
+ if ( $var == 1 || $var == true ) {
111
+ echo 'selected="selected"';
112
+ }
113
+ }
114
+ }
lite/includes/classes/class-es-post-notifications.php ADDED
@@ -0,0 +1,393 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ class ES_Post_Notifications_Table {
9
+
10
+ static $instance;
11
+
12
+ public function __construct() {
13
+
14
+ }
15
+
16
+ public function es_notifications_callback() {
17
+
18
+ $action = ig_es_get_request_data( 'action' );
19
+
20
+ ?>
21
+ <div class="wrap">
22
+ <?php if ( 'new' === $action ) {
23
+ $this->es_newnotification_callback();
24
+ } elseif ( 'edit' === $action ) {
25
+ $list = ig_es_get_request_data( 'list' );
26
+ $this->edit_list( absint( $list ) );
27
+ }
28
+ ?>
29
+ </div>
30
+ <?php
31
+ }
32
+
33
+ public function es_newnotification_callback() {
34
+
35
+ $submitted = ig_es_get_request_data( 'submitted' );
36
+ if ( 'submitted' === $submitted ) {
37
+
38
+ $list_id = ig_es_get_request_data( 'list_id' );
39
+ $template_id = ig_es_get_request_data( 'template_id' );
40
+ $cat = ig_es_get_request_data( 'es_note_cat' );
41
+ $es_note_cat_parent = ig_es_get_request_data( 'es_note_cat_parent' );
42
+ $cat = (!empty($es_note_cat_parent) && $es_note_cat_parent == '{a}All{a}') ? array($es_note_cat_parent) : $cat;
43
+
44
+ if ( empty( $list_id ) ) {
45
+ $message = __( 'Please select list.', 'email-subscribers' );
46
+ ES_Common::show_message( $message, 'error' );
47
+ $this->prepare_post_notification_form();
48
+
49
+ return;
50
+ }
51
+
52
+ if ( empty( $cat ) ) {
53
+ $message = __( 'Please select categories.', 'email-subscribers' );
54
+ ES_Common::show_message( $message, 'error' );
55
+ $this->prepare_post_notification_form();
56
+
57
+ return;
58
+ }
59
+
60
+ $type = 'post_notification';
61
+ $title = get_the_title( $template_id );
62
+
63
+ $data = array(
64
+ 'categories' => ES_Common::convert_categories_array_to_string( $cat ),
65
+ 'list_ids' => $list_id,
66
+ 'base_template_id' => $template_id,
67
+ 'status' => 1,
68
+ 'type' => $type,
69
+ 'name' => $title,
70
+ 'slug' => sanitize_title( $title )
71
+ );
72
+ $data = apply_filters( 'ig_es_post_notification_data', $data );
73
+ if ( empty( $data['base_template_id'] ) ) {
74
+ $message = __( 'Please select template.', 'email-subscribers' );
75
+ ES_Common::show_message( $message, 'error' );
76
+ $this->prepare_post_notification_form();
77
+
78
+ return;
79
+ }
80
+ $this->save_list( $data );
81
+ $type = ucwords(str_replace('_', ' ', $data['type']));
82
+ $message = __( "$type has been added successfully!", 'email-subscribers' );
83
+ ES_Common::show_message( $message, 'success' );
84
+ }
85
+
86
+ $this->prepare_post_notification_form();
87
+
88
+ }
89
+
90
+ public function custom_admin_notice() {
91
+ $es_note_cate = ig_es_get_request_data( 'es_note_cate' );
92
+
93
+ if ( $es_note_cate ) {
94
+ echo '<div class="updated"><p>Notification Added Successfully!</p></div>';
95
+ }
96
+ }
97
+
98
+ public function update_list( $id ) {
99
+
100
+ global $wpdb;
101
+ $cat = ig_es_get_request_data( 'es_note_cat' );
102
+ $data = array(
103
+ 'categories' => ES_Common::convert_categories_array_to_string( $cat ),
104
+ 'list_ids' => ig_es_get_request_data( 'list_id' ),
105
+ 'base_template_id' => ig_es_get_request_data( 'template_id' ),
106
+ 'status' => 'active'
107
+ );
108
+ $wpdb->update( IG_CAMPAIGNS_TABLE, $data, array( 'id' => $id ) );
109
+
110
+ }
111
+
112
+ public function save_list( $data, $id = null ) {
113
+ return ES()->campaigns_db->save_campaign( $data, $id );
114
+ }
115
+
116
+ /**
117
+ * Retrieve lists data from the database
118
+ *
119
+ * @param int $per_page
120
+ * @param int $page_number
121
+ *
122
+ * @return mixed
123
+ */
124
+ public static function get_lists( $per_page = 5, $page_number = 1 ) {
125
+
126
+ global $wpdb;
127
+
128
+ $order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
129
+ $order = ig_es_get_request_data( 'order' );
130
+ $search = ig_es_get_request_data( 's' );
131
+
132
+ $add_where_clause = false;
133
+ $sql = "SELECT * FROM " . IG_CAMPAIGNS_TABLE;
134
+ $args = array();
135
+ $query = array();
136
+
137
+ if ( ! empty( $search ) ) {
138
+ $add_where_clause = true;
139
+ $query[] = " name LIKE %s ";
140
+ $args[] = "%" . $wpdb->esc_like( $search ) . "%";
141
+ }
142
+
143
+ if ( $add_where_clause ) {
144
+ $sql .= " WHERE ";
145
+
146
+ if ( count( $query ) > 0 ) {
147
+ $sql .= implode( " AND ", $query );
148
+ $sql = $wpdb->prepare( $sql, $args );
149
+ }
150
+ }
151
+
152
+ // Prepare Order by clause
153
+ $order_by_clause = '';
154
+ if ( ! empty( $order_by ) ) {
155
+ $order_by_clause = ' ORDER BY ' . esc_sql( $order_by );
156
+ $order_by_clause .= ! empty( $order ) ? ' ' . esc_sql( $order ) : ' ASC';
157
+ }
158
+
159
+ $sql .= $order_by_clause;
160
+ $sql .= " LIMIT $per_page";
161
+ $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
162
+
163
+ $result = $wpdb->get_results( $sql, 'ARRAY_A' );
164
+
165
+ return $result;
166
+
167
+ }
168
+
169
+ public function edit_list( $id ) {
170
+
171
+ global $wpdb;
172
+
173
+ $notifications = $wpdb->get_results( "SELECT * FROM " . IG_CAMPAIGNS_TABLE . " WHERE id = $id LIMIT 0, 1", ARRAY_A );
174
+
175
+ $submitted = ig_es_get_request_data( 'submitted' );
176
+ if ( 'submitted' === $submitted ) {
177
+ $categories = ig_es_get_request_data( 'es_note_cat', array() );
178
+
179
+ //all categories selected
180
+ $parent_category_option = ig_es_get_request_data( 'es_note_cat_parent' );
181
+ if ( $parent_category_option === '{a}All{a}' ) {
182
+ array_unshift( $categories, $parent_category_option );
183
+ }
184
+
185
+ $data = array(
186
+ 'categories' => ES_Common::convert_categories_array_to_string( $categories ),
187
+ 'list_ids' => ig_es_get_request_data( 'list_id' ),
188
+ 'base_template_id' => ig_es_get_request_data( 'template_id' ),
189
+ 'status' => ig_es_get_request_data( 'status' )
190
+ );
191
+
192
+ $title = '';
193
+ if ( ! empty( $data['base_template_id'] ) ) {
194
+ $title = get_the_title( $data['base_template_id'] );
195
+ }
196
+ $data['name'] = $title;
197
+
198
+ $data = apply_filters( 'ig_es_post_notification_data', $data );
199
+ $data['type'] = !empty($data['type']) ? $data['type'] : 'post_notification';
200
+ //check tempalte id
201
+ if ( empty( $data['base_template_id'] ) ) {
202
+ $message = __( 'Please select template.', 'email-subscribers' );
203
+ ES_Common::show_message( $message, 'error' );
204
+ $this->prepare_post_notification_form( $id, $data );
205
+ return;
206
+ }
207
+ //check categories
208
+ if ( empty( $categories ) ) {
209
+ $message = __( 'Please select Categories.', 'email-subscribers' );
210
+ ES_Common::show_message( $message, 'error' );
211
+ $this->prepare_post_notification_form( $id, $data );
212
+ return;
213
+ }
214
+ $this->save_list( $data, $id );
215
+
216
+ $data['categories'] = ES_Common::convert_categories_string_to_array( $data['categories'], true );
217
+ $type = ucwords(str_replace('_', ' ', $data['type']));
218
+ $message = __( "$type has been updated successfully!", 'email-subscribers' );
219
+ ES_Common::show_message( $message, 'success' );
220
+ } else {
221
+
222
+ $notification = array_shift( $notifications );
223
+ $id = $notification['id'];
224
+
225
+ $categories_str = ! empty( $notification['categories'] ) ? $notification['categories'] : '';
226
+ $categories = ES_Common::convert_categories_string_to_array( $categories_str, true );
227
+ $data = array(
228
+ 'categories' => $categories,
229
+ 'list_ids' => $notification['list_ids'],
230
+ 'base_template_id' => $notification['base_template_id'],
231
+ 'status' => $notification['status']
232
+ );
233
+ }
234
+
235
+ $this->prepare_post_notification_form( $id, $data );
236
+
237
+ }
238
+
239
+ public static function prepare_post_notification_form( $id = '', $data = array() ) {
240
+
241
+ $is_new = empty( $id ) ? 1 : 0;
242
+
243
+ $action = 'new';
244
+ $heading = __( 'Campaigns > New Post Notification', 'email-subscribers' );
245
+ if ( ! $is_new ) {
246
+ $action = 'edit';
247
+ $heading = __( 'Campaigns > Edit Post Notification', 'email-subscribers' );
248
+ }
249
+ $cat = isset( $data['categories'] ) ? $data['categories'] : '';
250
+ $list_id = isset( $data['list_ids'] ) ? $data['list_ids'] : '';
251
+ $template_id = isset( $data['base_template_id'] ) ? $data['base_template_id'] : '';
252
+ $status = isset( $data['status'] ) ? $data['status'] : '';
253
+ $nonce = wp_create_nonce( 'es_post_notification' );
254
+ ?>
255
+
256
+ <div class="wrap">
257
+ <h2 class="wp-heading-inline"><?php echo $heading; ?>
258
+ <a href="admin.php?page=es_campaigns" class="page-title-action"><?php _e( 'Campaigns', 'email-subscribers' ) ?></a>
259
+ <?php if ( $action === 'edit' ) { ?>
260
+ <a href="admin.php?page=es_notifications&action=new" class="page-title-action"><?php _e( 'Add New', 'email-subscribers' ) ?></a>
261
+ <?php } ?>
262
+ <a href="edit.php?post_type=es_template" class="page-title-action es-imp-button"><?php _e( 'Manage Templates', 'email-subscribers' ) ?></a>
263
+ </h2>
264
+ <hr class="wp-header-end">
265
+ <div class="meta-box-sortables ui-sortable" style="width: 80%;display:inline;float:left">
266
+ <form method="post" action="admin.php?page=es_notifications&action=<?php echo $action; ?>&list=<?php echo $id; ?>&_wpnonce=<?php echo $nonce; ?>">
267
+ <table class="form-table">
268
+ <tbody>
269
+ <?php do_action('es_before_post_notification_settings', $id ); ?>
270
+ <tr>
271
+ <th scope="row">
272
+ <label for="tag-link"><?php _e( 'Select List', 'email-subscribers' ); ?></label>
273
+ <p class="helper"><?php _e( 'Contacts from the selected list will be notified about new post notification.', 'email-subscribers' ); ?></p>
274
+ </th>
275
+ <td>
276
+ <select name="list_id" id="ig_es_post_notification_list_ids">
277
+ <?php echo ES_Common::prepare_list_dropdown_options( $list_id ); ?>
278
+ </select>
279
+ </td>
280
+ </tr>
281
+ <tr>
282
+ <th scope="row">
283
+ <label for="tag-link">
284
+ <?php _e( 'Select template', 'email-subscribers' ); ?>
285
+ <p class="helper"><?php _e( 'Content of the selected template will be sent out as post notification.', 'email-subscribers' ); ?></p>
286
+ </label>
287
+ </th>
288
+ <td>
289
+ <select name="template_id" id="base_template_id">
290
+ <?php echo ES_Common::prepare_templates_dropdown_options( 'post_notification', $template_id ); ?>
291
+ </select>
292
+ </td>
293
+ </tr>
294
+ <?php do_action('es_after_post_notification_template', $id ); ?>
295
+ <?php if ( ! $is_new ) { ?>
296
+ <tr>
297
+ <th scope="row">
298
+ <label for="tag-link">
299
+ <?php _e( 'Select Status', 'email-subscribers' ); ?>
300
+ </label>
301
+ </th>
302
+ <td>
303
+ <select name="status" id="status">
304
+ <?php echo ES_Common::prepare_status_dropdown_options( $status ); ?>
305
+ </select>
306
+ </td>
307
+ </tr>
308
+ <?php } ?>
309
+ <tr>
310
+ <th scope="row">
311
+ <label for="tag-link"><?php _e( 'Select Post Category', 'email-subscribers' ); ?></label>
312
+ <p class="helper"><?php _e( 'Notification will be sent out when any post from selected categories will be published.', 'email-subscribers' ); ?></p>
313
+ </th>
314
+ <td style="vertical-align: top;">
315
+ <table border="0" cellspacing="0">
316
+ <tbody>
317
+ <?php echo ES_Common::prepare_categories_html( $cat ); ?>
318
+ </tbody>
319
+ </table>
320
+ </td>
321
+ </tr>
322
+ <tr>
323
+ <th scope="row">
324
+ <label for="tag-link">
325
+ <?php _e( 'Select custom post type(s)', 'email-subscribers' ); ?>
326
+ <p class="helper"><?php _e( '(Optional) Select custom post type for which you want to send notification.', 'email-subscribers' ); ?></p>
327
+ </label>
328
+ </th>
329
+ <td>
330
+ <table border="0" cellspacing="0">
331
+ <tbody>
332
+ <?php $custom_post_type = '';
333
+ echo ES_Common::prepare_custom_post_type_checkbox( $cat ); ?>
334
+ </tbody>
335
+ </table>
336
+ </td>
337
+ </tr>
338
+ <?php do_action('es_after_post_notification_settings', $id ); ?>
339
+ <tr>
340
+ <td><input type="hidden" name="submitted" value="submitted"></td>
341
+ </tr>
342
+ </tbody>
343
+ </table>
344
+ <div class="row-blog">
345
+ <div class="leftside">
346
+ <p class="submit"><input type="submit" name="submit" id="ig_es_campaign_post_notification_submit_button" class="button button-primary button-large" value="Save Changes"></p>
347
+ </div>
348
+ </div>
349
+ </form>
350
+ </div>
351
+ <div clas="es-preview" style="float: right;width: 19%;">
352
+ <div class="es-templ-img"></div>
353
+ </div>
354
+ </div>
355
+
356
+ <?php
357
+
358
+ }
359
+
360
+
361
+ /**
362
+ * Returns an associative array containing the bulk action
363
+ *
364
+ * @return array
365
+ */
366
+ public function get_bulk_actions() {
367
+ $actions = array(
368
+ 'bulk_delete' => 'Delete'
369
+ );
370
+
371
+ return $actions;
372
+ }
373
+
374
+ public function search_box( $text, $input_id ) { ?>
375
+ <p class="search-box">
376
+ <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
377
+ <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>"/>
378
+ <?php submit_button( 'Search Notifications', 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
379
+ </p>
380
+ <?php
381
+ }
382
+
383
+ public static function get_instance() {
384
+ if ( ! isset( self::$instance ) ) {
385
+ self::$instance = new self();
386
+ }
387
+
388
+ return self::$instance;
389
+ }
390
+
391
+ }
392
+
393
+
lite/includes/classes/class-es-queue.php ADDED
@@ -0,0 +1,737 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ if ( ! class_exists( 'ES_Queue' ) ) {
8
+ /**
9
+ * Class ES_Queue
10
+ *
11
+ * Manage Mailing Queue
12
+ *
13
+ * Actions
14
+ * ig_es_time_based_campaign - Immediately, Daily, Weekly, Monthly
15
+ * ig_es_contact_insert - Time after contact subscribe
16
+ * ig_es_campaign_open - Time after specific campaign open
17
+ *
18
+ * @since 4.2.0
19
+ */
20
+ class ES_Queue {
21
+ /**
22
+ * ES_DB_Queue object
23
+ *
24
+ * @since 4.2.1
25
+ * @var $db
26
+ *
27
+ */
28
+ protected $db;
29
+
30
+ /**
31
+ * ES_Queue constructor.
32
+ *
33
+ * @since 4.2.0
34
+ */
35
+ public function __construct() {
36
+
37
+ $this->db = new ES_DB_Queue();
38
+
39
+ add_action( 'plugins_loaded', array( &$this, 'init' ), 1 );
40
+
41
+ add_action( 'ig_es_before_message_send', array( &$this, 'set_sending_status' ), 10, 3 );
42
+ add_action( 'ig_es_message_sent', array( &$this, 'set_sent_status' ), 10, 3 );
43
+ add_action( 'ig_es_message_sent', array( &$this, 'update_email_sent_count' ), 10, 3 );
44
+ }
45
+
46
+ /**
47
+ * Initialize Queue
48
+ *
49
+ * @since 4.2.0
50
+ */
51
+ public function init() {
52
+ add_action( 'ig_es_cron_auto_responder', array( &$this, 'queue_time_based_campaigns' ), 30 );
53
+ add_action( 'ig_es_cron_auto_responder', array( &$this, 'queue_sequences' ), 30 );
54
+
55
+ add_action( 'ig_es_cron_worker', array( &$this, 'process_campaigns' ), 10 );
56
+ add_action( 'ig_es_cron_worker', array( &$this, 'process_queue' ), 30 );
57
+ }
58
+
59
+ /**
60
+ * Queue valid time based campaigns
61
+ *
62
+ * @since 4.2.0
63
+ */
64
+ public function queue_time_based_campaigns( $campaign_id = 0, $force = false ) {
65
+ /**
66
+ * Steps
67
+ * 1. Fetch all active campaigns
68
+ * 2. Loop over through and based on matched condition put campaign into mailing_queue table
69
+ * 3. And also insert subscribers for respective campaign into sending_queue_table
70
+ * 4. Call es cron to send emails from queue
71
+ */
72
+ static $campaigns_to_process;
73
+
74
+ if ( ! isset( $campaigns_to_process ) ) {
75
+ $campaigns_to_process = array();
76
+ }
77
+
78
+ if ( $campaign_id ) {
79
+ $campaign = ES()->campaigns_db->get_campaign_by_id( $campaign_id );
80
+ $campaigns = array( $campaign );
81
+ } else {
82
+ $campaigns = ES()->campaigns_db->get_active_campaigns( IG_CAMPAIGN_TYPE_POST_DIGEST );
83
+ }
84
+
85
+ if ( empty( $campaigns ) ) {
86
+ return;
87
+ }
88
+
89
+ $now = time();
90
+
91
+ foreach ( $campaigns as $campaign ) {
92
+
93
+ if ( in_array( $campaign['id'], $campaigns_to_process ) && ! $force ) {
94
+ continue;
95
+ }
96
+
97
+ $campaign_id = $campaign['id'];
98
+
99
+ $campaigns_to_process[] = $campaign_id;
100
+
101
+ $meta = maybe_unserialize( $campaign['meta'] );
102
+
103
+ $rules = ! empty( $meta['rules'] ) ? $meta['rules'] : array();
104
+
105
+ if ( ! empty( $rules ) ) {
106
+
107
+ $action = ! empty( $rules['action'] ) ? $rules['action'] : '';
108
+
109
+ if ( 'ig_es_time_based_campaign' != $action ) {
110
+ continue;
111
+ }
112
+
113
+ $start_time = ! empty( $meta['next_run'] ) ? $meta['next_run'] : 0;
114
+
115
+ if ( ! empty( $start_time ) ) {
116
+
117
+ $scheduled = ! empty( $meta['scheduled'] ) ? $meta['scheduled'] : 0;
118
+
119
+ $delay = $start_time - $now;
120
+
121
+ // seconds the campaign should created before the actual send time.
122
+ $time_created_before = 3600;
123
+
124
+ // Is it a good time to do now?
125
+ $do_it = $delay <= $time_created_before;
126
+
127
+ // By default do not schedule
128
+ if ( $do_it && ! $scheduled ) {
129
+
130
+ $campaign['start_at'] = date( 'Y-m-d H:i:s', $start_time );
131
+
132
+ $list_id = $campaign['list_ids'];
133
+
134
+ // Do we have active subscribers?
135
+ $contacts = ES()->contacts_db->get_active_contacts_by_list_id( $list_id );
136
+ $total_contacts = count( $contacts );
137
+
138
+ if ( $total_contacts > 0 ) {
139
+ // Create a new mailing queue using this campaign
140
+ $result = $this->add_campaign_to_queue( $campaign, $total_contacts );
141
+
142
+ if ( is_array( $result ) ) {
143
+ $queue_id = $result['id'];
144
+ $hash = $result['hash'];
145
+
146
+ $this->add_contacts_to_queue( $campaign_id, $hash, $queue_id, $contacts );
147
+ }
148
+
149
+ }
150
+ }
151
+
152
+ $time_frame = ! empty( $rules['time_frame'] ) ? $rules['time_frame'] : '';
153
+
154
+ if ( 'immediately' !== $time_frame ) {
155
+
156
+ $data = array(
157
+ 'utc_start' => $start_time,
158
+ 'interval' => $rules['interval'],
159
+ 'time_frame' => $time_frame,
160
+ 'time_of_day' => $rules['time_of_day'],
161
+ 'weekdays' => $rules['weekdays'],
162
+ 'force' => true
163
+ );
164
+
165
+ // Get the next run time.
166
+ $next_run = ig_es_get_next_future_schedule_date( $data );
167
+
168
+ $meta_data['next_run'] = $next_run;
169
+ if ( $next_run == $start_time ) {
170
+ $meta_data['scheduled'] = 1;
171
+ } else {
172
+ $meta_data['scheduled'] = 0;
173
+ }
174
+
175
+ } else {
176
+ $meta_data['scheduled'] = 1;
177
+ }
178
+
179
+ ES()->campaigns_db->update_campaign_meta( $campaign_id, $meta_data );
180
+ }
181
+ }
182
+ }
183
+
184
+ }
185
+
186
+ /**
187
+ * Queue Valid Sequence messages
188
+ *
189
+ * @since 4.2.1
190
+ */
191
+ public function queue_sequences( $campaign_id = 0, $force = false ) {
192
+ global $wpdb;
193
+ /**
194
+ * Steps
195
+ * 1. Fetch all active Sequence Message
196
+ * 2. Loop over through and based on matched condition put campaign into mailing_queue table if not already exists
197
+ * 3. And also insert subscribers for respective campaign into snding_queue_table
198
+ */
199
+ static $campaigns_to_process;
200
+
201
+ if ( ! isset( $campaigns_to_process ) ) {
202
+ $campaigns_to_process = array();
203
+ }
204
+
205
+ if ( $campaign_id ) {
206
+ $campaign = ES()->campaigns_db->get_campaign_by_id( $campaign_id );
207
+ $campaigns = array( $campaign );
208
+ } else {
209
+ $campaigns = ES()->campaigns_db->get_active_campaigns( IG_CAMPAIGN_TYPE_SEQUENCE_MESSAGE );
210
+ }
211
+
212
+ if ( empty( $campaigns ) ) {
213
+ return;
214
+ }
215
+
216
+ $now = time();
217
+
218
+ foreach ( $campaigns as $campaign ) {
219
+
220
+ if ( in_array( $campaign['id'], $campaigns_to_process ) && ! $force ) {
221
+ continue;
222
+ }
223
+
224
+ $campaign_id = $campaign['id'];
225
+
226
+ $campaigns_to_process[] = $campaign_id;
227
+
228
+ $meta = maybe_unserialize( $campaign['meta'] );
229
+
230
+ $rules = ! empty( $meta['rules'] ) ? $meta['rules'] : array();
231
+
232
+ //ES()->logger->info( 'Rules: ' . print_r( $rules, true ) );
233
+
234
+ if ( ! empty( $rules ) ) {
235
+
236
+ $action = ! empty( $rules['action'] ) ? $rules['action'] : '';
237
+
238
+ if ( 'ig_es_contact_insert' != $action ) {
239
+ continue;
240
+ }
241
+
242
+ // We are considering contacts for sequences which are last added in a week.
243
+ $grace_period = 1 * DAY_IN_SECONDS;
244
+ $queue_upfront = 3600;
245
+
246
+ $offset = (int) $rules['amount'] . ' ' . strtoupper( $rules['unit'] );
247
+
248
+ $list_ids = $campaign['list_ids'];
249
+
250
+ $ig_actions_table = IG_ACTIONS_TABLE;
251
+ $ig_lists_contacts_table = IG_LISTS_CONTACTS_TABLE;
252
+ $ig_queue_table = IG_QUEUE_TABLE;
253
+ $ig_campaign_sent = IG_MESSAGE_SENT;
254
+
255
+ $query_args = array(
256
+ "select" => "SELECT lists_contacts.contact_id, UNIX_TIMESTAMP ( lists_contacts.subscribed_at + INTERVAL $offset ) AS timestamp",
257
+ "from" => "FROM $ig_lists_contacts_table AS lists_contacts",
258
+ 'join1' => "LEFT JOIN $ig_actions_table AS actions_sent_message ON lists_contacts.contact_id = actions_sent_message.contact_id AND actions_sent_message.type = $ig_campaign_sent AND actions_sent_message.campaign_id IN ($campaign_id)",
259
+ 'join2' => "LEFT JOIN $ig_queue_table AS queue ON lists_contacts.contact_id = queue.contact_id AND queue.campaign_id IN ($campaign_id)",
260
+ 'where' => "WHERE 1=1 AND lists_contacts.list_id IN ($list_ids) AND lists_contacts.status = 'subscribed' AND actions_sent_message.contact_id IS NULL AND queue.contact_id IS NULL",
261
+ 'group_by' => "GROUP BY lists_contacts.contact_id",
262
+ 'having' => "HAVING timestamp <= " . ( $now + $queue_upfront ) . " AND timestamp >= " . ( $now - $grace_period ),
263
+ 'order_by' => 'ORDER BY timestamp ASC',
264
+ );
265
+
266
+ $query = implode( ' ', $query_args );
267
+
268
+ //ES()->logger->info( '----------------------------Query Args (ig_es_contact_insert) ----------------------------' );
269
+ //ES()->logger->info( $query );
270
+ //ES()->logger->info( '----------------------------Query Args Complete (ig_es_contact_insert) ----------------------------' );
271
+
272
+ $results = $wpdb->get_results( $query, ARRAY_A );
273
+
274
+ //ES()->logger->info( 'Results: ' . print_r( $results, true ) );
275
+
276
+ if ( ! empty( $results ) ) {
277
+
278
+ $contact_ids = wp_list_pluck( $results, 'contact_id' );
279
+ $timestamps = wp_list_pluck( $results, 'timestamp' );
280
+
281
+ /**
282
+ * Check whether campaign is already exists in mailing_queue table with $campaign_id
283
+ * If Exists, Get the mailing_queue_id & hash
284
+ * If Not, create new and get the mailing_queue_id & hash
285
+ */
286
+ $total_contacts = count( $contact_ids );
287
+ if ( $total_contacts > 0 ) {
288
+
289
+ $this->bulk_add( $campaign_id, $contact_ids, $timestamps, 15 );
290
+
291
+ $timestamp = min( $timestamps );
292
+
293
+ // handle instant delivery
294
+ if ( $timestamp - time() <= 0 ) {
295
+ wp_schedule_single_event( $timestamp, 'ig_es_cron_worker', array( $campaign_id ) );
296
+ }
297
+
298
+ }
299
+ }
300
+
301
+ }
302
+ }
303
+
304
+
305
+ }
306
+
307
+ /**
308
+ * Add campaign to queue
309
+ *
310
+ * @param $campaign
311
+ *
312
+ * @return int | array
313
+ *
314
+ * @since 4.2.0
315
+ */
316
+ public function add_campaign_to_queue( $campaign, $total_contacts ) {
317
+
318
+ $campaign_id = $campaign['id'];
319
+ $template_id = $campaign['base_template_id'];
320
+ $template = get_post( $template_id );
321
+ $queue_id = 0;
322
+ if ( $template instanceof WP_Post && $total_contacts > 0 ) {
323
+
324
+ $subject = ! empty( $template->post_title ) ? $template->post_title : '';
325
+ $content = ! empty( $template->post_content ) ? $template->post_content : '';
326
+ $content = ES_Common::es_process_template_body( $content, $template_id );
327
+
328
+ $guid = ES_Common::generate_guid( 6 );
329
+
330
+ $data = array(
331
+ 'hash' => $guid,
332
+ 'campaign_id' => $campaign_id,
333
+ 'subject' => $subject,
334
+ 'body' => $content,
335
+ 'count' => $total_contacts,
336
+ 'status' => 'In Queue',
337
+ 'start_at' => ! empty( $campaign['start_at'] ) ? $campaign['start_at'] : '',
338
+ 'finish_at' => '',
339
+ 'created_at' => ig_get_current_date_time(),
340
+ 'updated_at' => ig_get_current_date_time(),
341
+ 'meta' => maybe_serialize( array( 'type' => $campaign['type'] ) )
342
+ );
343
+
344
+ $queue_id = ES_DB_Mailing_Queue::add_notification( $data );
345
+
346
+ return array(
347
+ 'hash' => $guid,
348
+ 'id' => $queue_id
349
+ );
350
+
351
+ }
352
+
353
+ return $queue_id;
354
+ }
355
+
356
+ /**
357
+ * Add contacts into sending_queue_table
358
+ *
359
+ * @param $campaign_id
360
+ * @param $guid
361
+ * @param $queue_id
362
+ * @param $contacts
363
+ *
364
+ * @since 4.2.1
365
+ */
366
+ public function add_contacts_to_queue( $campaign_id, $guid, $queue_id, $contacts ) {
367
+
368
+ $delivery_data = array();
369
+ $delivery_data['hash'] = $guid;
370
+ $delivery_data['subscribers'] = $contacts;
371
+ $delivery_data['campaign_id'] = $campaign_id;
372
+ $delivery_data['mailing_queue_id'] = $queue_id;
373
+
374
+ ES_DB_Sending_Queue::do_batch_insert( $delivery_data );
375
+ }
376
+
377
+ /**
378
+ * Bulk Add contacts into queue
379
+ *
380
+ * @param $campaign_id
381
+ * @param $subscribers
382
+ * @param null $timestamp
383
+ * @param int $priority
384
+ * @param bool $clear
385
+ * @param bool $ignore_status
386
+ * @param bool $reset
387
+ * @param bool $options
388
+ * @param bool $tags
389
+ *
390
+ * @return bool|void
391
+ *
392
+ * @since 4.2.1
393
+ */
394
+ public function bulk_add( $campaign_id, $subscribers, $timestamp = null, $priority = 10, $clear = false, $ignore_status = false, $reset = false, $options = false, $tags = false ) {
395
+
396
+ global $wpdb;
397
+
398
+ if ( $clear ) {
399
+ $this->clear( $campaign_id, $subscribers );
400
+ }
401
+
402
+ if ( empty( $subscribers ) ) {
403
+ return;
404
+ }
405
+
406
+ if ( is_null( $timestamp ) ) {
407
+ $timestamp = time();
408
+ }
409
+
410
+ $timestamps = ! is_array( $timestamp )
411
+ ? array_fill( 0, count( $subscribers ), $timestamp )
412
+ : $timestamp;
413
+
414
+ $now = time();
415
+
416
+ $campaign_id = (int) $campaign_id;
417
+ $subscribers = array_filter( $subscribers, 'is_numeric' );
418
+
419
+ if ( $tags ) {
420
+ $tags = maybe_serialize( $tags );
421
+ }
422
+ if ( $options ) {
423
+ $options = maybe_serialize( $options );
424
+ }
425
+
426
+ if ( empty( $subscribers ) ) {
427
+ return true;
428
+ }
429
+
430
+ $inserts = array();
431
+
432
+ foreach ( $subscribers as $i => $subscriber_id ) {
433
+ $inserts[] = "($subscriber_id,$campaign_id,$now," . $timestamps[ $i ] . ",$priority,1,'$ignore_status','$options','$tags')";
434
+ }
435
+
436
+ $chunks = array_chunk( $inserts, 1000 );
437
+
438
+ $success = true;
439
+
440
+ foreach ( $chunks as $insert ) {
441
+
442
+ $sql = "INSERT INTO {$wpdb->prefix}ig_queue (contact_id, campaign_id, added, timestamp, priority, count, ignore_status, options, tags) VALUES";
443
+
444
+ $sql .= ' ' . implode( ',', $insert );
445
+
446
+ $sql .= ' ON DUPLICATE KEY UPDATE timestamp = values(timestamp), ignore_status = values(ignore_status)';
447
+ if ( $reset ) {
448
+ $sql .= ', sent = 0';
449
+ }
450
+ if ( $options ) {
451
+ $sql .= sprintf( ", options = '%s'", $options );
452
+ }
453
+ if ( $tags ) {
454
+ $sql .= sprintf( ", tags = '%s'", $tags );
455
+ }
456
+
457
+ //ES()->logger->info( 'Adding Bulk SQL: ' . $sql );
458
+
459
+ $success = $success && false !== $wpdb->query( $sql );
460
+
461
+ }
462
+
463
+ return $success;
464
+
465
+ }
466
+
467
+ /**
468
+ * Clear queue which are not assigned to any campaign
469
+ *
470
+ * @param null $campaign_id
471
+ * @param array $subscribers
472
+ *
473
+ * @return bool
474
+ *
475
+ * @since 4.2.1
476
+ */
477
+ public function clear( $campaign_id = null, $subscribers = array() ) {
478
+
479
+ global $wpdb;
480
+
481
+ $campaign_id = (int) $campaign_id;
482
+ $subscribers = array_filter( $subscribers, 'is_numeric' );
483
+
484
+ if ( empty( $subscribers ) ) {
485
+ $subscribers = array( - 1 );
486
+ }
487
+
488
+ $sql = "DELETE queue FROM {$wpdb->prefix}ig_queue AS queue WHERE queue.sent = 0 AND queue.contact_id NOT IN (" . implode( ',', $subscribers ) . ')';
489
+ if ( ! is_null( $campaign_id ) ) {
490
+ $sql .= $wpdb->prepare( ' AND queue.campaign_id = %d', $campaign_id );
491
+ }
492
+
493
+ return false !== $wpdb->query( $sql );
494
+
495
+ }
496
+
497
+ /**
498
+ * Process Queue
499
+ *
500
+ * @since 4.2.1
501
+ */
502
+ public function process_queue() {
503
+ global $wpdb;
504
+
505
+ $micro_time = microtime( true );
506
+
507
+ $ig_queue_table = IG_QUEUE_TABLE;
508
+ $ig_campaigns_table = IG_CAMPAIGNS_TABLE;
509
+
510
+ $sql = 'SELECT queue.campaign_id, queue.contact_id, queue.count AS _count, queue.requeued AS _requeued, queue.options AS _options, queue.tags AS _tags, queue.priority AS _priority';
511
+ $sql .= " FROM $ig_queue_table AS queue";
512
+ $sql .= " LEFT JOIN $ig_campaigns_table AS campaigns ON campaigns.id = queue.campaign_id";
513
+ $sql .= ' WHERE queue.timestamp <= ' . (int) $micro_time . " AND queue.sent_at = 0";
514
+ $sql .= " AND (campaigns.status = 1)";
515
+ $sql .= ' ORDER BY queue.priority DESC';
516
+
517
+ //ES()->logger->info( 'Process Queue:' );
518
+ //ES()->logger->info( 'SQL: ' . $sql );
519
+
520
+ $notifications = $wpdb->get_results( $sql, ARRAY_A );
521
+
522
+ if ( is_array( $notifications ) && count( $notifications ) > 0 ) {
523
+ $campaigns_notifications = $contact_ids = array();
524
+ foreach ( $notifications as $notification ) {
525
+ $campaigns_notifications[ $notification['campaign_id'] ][] = $notification;
526
+
527
+ $contact_ids[] = $notification['contact_id'];
528
+ }
529
+
530
+ // We need unique ids
531
+ $contact_ids = array_unique( $contact_ids );
532
+
533
+ $contacts = ES()->contacts_db->get_details_by_ids( $contact_ids );
534
+
535
+ foreach ( $campaigns_notifications as $campaign_id => $notifications ) {
536
+
537
+ $campaign = ES()->campaigns_db->get( $campaign_id );
538
+
539
+ if ( ! empty( $campaign ) ) {
540
+
541
+ $content = $campaign['body'];
542
+ $subject = $campaign['subject'];
543
+
544
+ foreach ( $notifications as $notification ) {
545
+
546
+ $contact_id = $notification['contact_id'];
547
+
548
+ if ( ! empty( $contacts[ $contact_id ] ) ) {
549
+
550
+ $first_name = $contacts[ $contact_id ]['first_name'];
551
+ $last_name = $contacts[ $contact_id ]['last_name'];
552
+ $hash = $contacts[ $contact_id ]['hash'];
553
+ $email = $contacts[ $contact_id ]['email'];
554
+ $name = ES_Common::prepare_name_from_first_name_last_name( $first_name, $last_name );
555
+
556
+ $merge_tags = array(
557
+ 'name' => $name,
558
+ 'first_name' => $first_name,
559
+ 'last_name' => $last_name,
560
+ 'email' => $email,
561
+ 'guid' => $hash,
562
+ 'dbid' => $contact_id,
563
+ 'message_id' => 0,
564
+ 'campaign_id' => $campaign_id
565
+ );
566
+
567
+ $result = ES()->mailer->send( $subject, $content, $email, $merge_tags );
568
+
569
+ do_action( 'ig_es_message_sent', $contact_id, $campaign_id, 0 );
570
+
571
+ // Email Sent now delete from queue now.
572
+ $this->db->delete_from_queue( $campaign_id, $contact_id );
573
+ }
574
+ }
575
+ }
576
+
577
+ }
578
+
579
+ }
580
+
581
+
582
+ }
583
+
584
+ /**
585
+ * Process Campaigns and send notifications
586
+ *
587
+ * @since 4.3.1
588
+ */
589
+ public function process_campaigns() {
590
+ /**
591
+ * - Get GUID from ig_es_mailing_queue table which are in queue
592
+ * - Get contacts from the ig_es_sending_queue table based on fetched guid
593
+ * - Prepare email content
594
+ * - Send emails based on fetched contacts
595
+ * - Update status in ig_es_mailing_queue table
596
+ * - Update status in ig_es_sending_queue table
597
+ */
598
+ $es_c_croncount = ES_Common::total_emails_to_be_sent();
599
+
600
+ if ( $es_c_croncount > 0 ) {
601
+
602
+ // Get GUID from sentdetails report which are in queue
603
+ $campaign_hash = ig_es_get_request_data( 'campaign_hash' );
604
+
605
+ $notification = ES_DB_Mailing_Queue::get_notification_to_be_sent( $campaign_hash );
606
+ $notification_guid = isset( $notification['hash'] ) ? $notification['hash'] : null;
607
+ $message_id = isset( $notification['id'] ) ? $notification['id'] : 0;
608
+ $campaign_id = isset( $notification['campaign_id'] ) ? $notification['campaign_id'] : 0;
609
+
610
+ if ( ! is_null( $notification_guid ) ) {
611
+ ES_DB_Mailing_Queue::update_sent_status( $notification_guid, 'Sending' );
612
+
613
+ // Get subscribers from the sending_queue table based on fetched guid
614
+ $emails_data = ES_DB_Sending_Queue::get_emails_to_be_sent_by_hash( $notification_guid, $es_c_croncount );
615
+ $total_emails = count( $emails_data );
616
+ // Found Subscribers to send notification?
617
+ if ( $total_emails > 0 ) {
618
+ $ids = $emails = array();
619
+ foreach ( $emails_data as $email ) {
620
+ $ids[] = $email['id'];
621
+ $emails[] = $email['email'];
622
+ }
623
+
624
+ $merge_tags = array(
625
+ 'guid' => $notification_guid,
626
+ 'message_id' => $message_id,
627
+ 'campaign_id' => $campaign_id,
628
+ );
629
+
630
+ $subject = $notification['subject'];
631
+ $content = $notification['body'];
632
+
633
+ ES()->mailer->send( $subject, $content, $emails, $merge_tags );
634
+
635
+ $total_remaining_emails = ES_DB_Sending_Queue::get_total_emails_to_be_sent_by_hash( $notification_guid );
636
+ $remaining_emails_to_be_sent = ES_DB_Sending_Queue::get_total_emails_to_be_sent();
637
+
638
+ // No emails left for the $notification_guid??? Send admin notification for the
639
+ // Completion of a job
640
+ if ( $total_remaining_emails == 0 ) {
641
+ ES_DB_Mailing_Queue::update_sent_status( $notification_guid, 'Sent' );
642
+
643
+ // Send Cron Email to admins
644
+ ES()->mailer->send_cron_admin_email( $notification_guid );
645
+ }
646
+
647
+ //TODO: Implement better solution
648
+ set_transient( 'ig_es_total_emails_sent', $total_emails, MINUTE_IN_SECONDS );
649
+ set_transient( 'ig_es_remaining_email_count', $remaining_emails_to_be_sent, MINUTE_IN_SECONDS );
650
+
651
+ $response['total_emails_sent'] = $total_emails;
652
+ $response['es_remaining_email_count'] = $remaining_emails_to_be_sent;
653
+ $response['message'] = 'EMAILS_SENT';
654
+ $response['status'] = 'SUCCESS';
655
+ // update last cron run time
656
+ update_option( 'ig_es_last_cron_run', time() );
657
+ } else {
658
+ $response['es_remaining_email_count'] = 0;
659
+ $response['message'] = 'EMAILS_NOT_FOUND';
660
+ $response['status'] = 'SUCCESS';
661
+ ES_DB_Mailing_Queue::update_sent_status( $notification_guid, 'Sent' );
662
+ }
663
+ } else {
664
+ $response['es_remaining_email_count'] = 0;
665
+ $response['message'] = 'NOTIFICATION_NOT_FOUND';
666
+ $response['status'] = 'SUCCESS';
667
+ }
668
+ } else {
669
+ $self = false;
670
+ $response['status'] = 'ERROR';
671
+ $response['message'] = 'EMAIL_SENDING_LIMIT_EXCEEDED';
672
+ }
673
+ }
674
+
675
+ /**
676
+ * Update Email Sent Count
677
+ *
678
+ * @param int $contact_id
679
+ * @param int $campaign_id
680
+ * @param int $message_id
681
+ *
682
+ * @since 4.3.2
683
+ */
684
+ public function update_email_sent_count( $contact_id = 0, $campaign_id = 0, $message_id = 0 ) {
685
+ ES_Common::update_total_email_sent_count();
686
+ }
687
+
688
+ /**
689
+ * Update email sent status in a queue
690
+ *
691
+ * @param int $contact_id
692
+ * @param int $campaign_id
693
+ * @param int $message_id
694
+ *
695
+ * @since 4.3.2
696
+ */
697
+ public function update_email_sent_status( $contact_id = 0, $campaign_id = 0, $message_id = 0, $status = 'Sent' ) {
698
+ ES_DB_Sending_Queue::update_sent_status( $contact_id, $message_id, $status );
699
+ }
700
+
701
+ /**
702
+ * Set "Sending" status
703
+ *
704
+ * @param int $contact_id
705
+ * @param int $campaign_id
706
+ * @param int $message_id
707
+ *
708
+ * @since 4.3.2
709
+ */
710
+ public function set_sending_status( $contact_id = 0, $campaign_id = 0, $message_id = 0 ) {
711
+
712
+ if ( 0 != $contact_id && 0 != $message_id ) {
713
+ $this->update_email_sent_status( $contact_id, $campaign_id, $message_id, 'Sending' );
714
+ }
715
+ }
716
+
717
+ /**
718
+ * Set "Sent" status
719
+ *
720
+ * @param int $contact_id
721
+ * @param int $campaign_id
722
+ * @param int $message_id
723
+ *
724
+ * @since 4.3.2
725
+ */
726
+ public function set_sent_status( $contact_id = 0, $campaign_id = 0, $message_id = 0 ) {
727
+
728
+ if ( 0 != $contact_id && 0 != $message_id ) {
729
+ $this->update_email_sent_status( $contact_id, $campaign_id, $message_id, 'Sent' );
730
+ }
731
+ }
732
+
733
+ }
734
+ }
735
+
736
+
737
+
lite/includes/classes/class-es-reports-data.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ if ( ! class_exists( 'ES_Reports_Data' ) ) {
9
+ /**
10
+ * Get Reports Data
11
+ * Class ES_Reports_Data
12
+ *
13
+ * @since 4.3.2
14
+ */
15
+ class ES_Reports_Data {
16
+
17
+ /**
18
+ * Get total Contacts
19
+ *
20
+ * @since 4.3.2
21
+ */
22
+ public static function get_total_contacts() {
23
+ return ES()->contacts_db->get_total_contacts();
24
+ }
25
+
26
+ /**
27
+ * Get total subscribed contacts in last $days
28
+ *
29
+ * @param int $days
30
+ *
31
+ * @return int
32
+ */
33
+ public static function get_total_subscribed_contacts( $days = 0 ) {
34
+ return ES_DB_Lists_Contacts::get_total_subscribed_contacts( $days );
35
+ }
36
+
37
+ /**
38
+ * Get total unsubscribed contacts in last $days
39
+ *
40
+ * @param int $days
41
+ *
42
+ * @return int
43
+ */
44
+ public static function get_total_unsubscribed_contacts( $days = 0 ) {
45
+ return ES_DB_Lists_Contacts::get_total_unsubscribed_contacts( $days );
46
+ }
47
+
48
+ /**
49
+ * Get total contacts have opened emails in last $days
50
+ *
51
+ * @param int $days
52
+ *
53
+ * @return int
54
+ */
55
+ public static function get_total_contacts_opened_emails( $days = 60 ) {
56
+ return ES_DB_Sending_Queue::get_total_contacts_opened_emails( $days );
57
+ }
58
+
59
+ /**
60
+ * Get total contacts have clicked on links in emails in last $days
61
+ *
62
+ * @param int $days
63
+ *
64
+ * @return int
65
+ */
66
+ public static function get_total_contacts_clicks_links( $days = 60 ) {
67
+ return ES()->actions_db->get_total_contacts_clicks_links( $days );
68
+ }
69
+
70
+
71
+ }
72
+ }
lite/includes/classes/class-es-reports-table.php ADDED
@@ -0,0 +1,518 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ if ( ! class_exists( 'WP_List_Table' ) ) {
9
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
10
+ }
11
+
12
+ class ES_Reports_Table extends WP_List_Table {
13
+
14
+ static $instance;
15
+
16
+ public function __construct() {
17
+
18
+ parent::__construct( array(
19
+ 'singular' => __( 'Report', 'email-subscribers' ), //singular name of the listed records
20
+ 'plural' => __( 'Reports', 'email-subscribers' ), //plural name of the listed records
21
+ 'ajax' => false, //does this table support ajax?,
22
+ 'screen' => 'es_reports'
23
+ ) );
24
+ }
25
+
26
+ public function es_reports_callback() {
27
+
28
+ $action = ig_es_get_request_data( 'action' );
29
+ if ( 'view' === $action ) {
30
+ $list = ig_es_get_request_data( 'list' );
31
+ $this->view_list( $list );
32
+ } else {
33
+ ?>
34
+
35
+ <div class="wrap">
36
+ <h1 class="wp-heading-inline"><?php _e( 'Reports', 'email-subscribers' ); ?></h1>
37
+ <?php
38
+ $emails_to_be_sent = ES_DB_Sending_Queue::get_total_emails_to_be_sent();
39
+ if ( $emails_to_be_sent > 0 ) {
40
+ $cron_url = ES()->cron->url( true );
41
+ $content = sprintf( __( "<a href='%s' target='_blank' class='page-title-action es-imp-button'>Send Queued Emails Now</a>", 'email-subscribers' ), $cron_url );
42
+ } else {
43
+ $content = sprintf( __( "<span class='page-title-action button-disabled'>Send Queued Emails Now</span>", 'email-subscribers' ) );
44
+ $content .= sprintf( __( "<br /><span class='es-helper'>No emails found in queue</span>", 'email-subscribers' ) );
45
+ }
46
+ ?>
47
+
48
+ <span class="ig-es-process-queue"><?php echo $content; ?></span>
49
+
50
+
51
+ <div id="poststuff">
52
+ <div id="post-body" class="metabox-holder column-1">
53
+ <div id="post-body-content">
54
+ <div class="meta-box-sortables ui-sortable">
55
+ <form method="post">
56
+ <?php
57
+ $this->prepare_items();
58
+ $this->display(); ?>
59
+ </form>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ <br class="clear">
64
+ </div>
65
+ </div>
66
+
67
+ <?php
68
+ }
69
+ }
70
+
71
+ public function screen_option() {
72
+
73
+ $option = 'per_page';
74
+ $args = array(
75
+ 'label' => __( 'Reports', 'email-subscribers' ),
76
+ 'default' => 10,
77
+ 'option' => 'reports_per_page'
78
+ );
79
+
80
+ add_screen_option( $option, $args );
81
+
82
+ }
83
+
84
+ public function prepare_header_footer_row() {
85
+
86
+ ?>
87
+
88
+ <tr>
89
+ <th width="6%" scope="col"><?php _e( 'Sr No', 'email-subscribers' ); ?></th>
90
+ <th scope="col"><?php _e( 'Email', 'email-subscribers' ); ?></th>
91
+ <th scope="col"><?php _e( 'Status', 'email-subscribers' ); ?></th>
92
+ <th scope="col"><?php _e( 'Sent Date', 'email-subscribers' ); ?></th>
93
+ <th scope="col"><?php _e( 'Viewed Status', 'email-subscribers' ); ?></th>
94
+ <th scope="col"><?php _e( 'Viewed Date', 'email-subscribers' ); ?></th>
95
+ </tr>
96
+
97
+ <?php
98
+ }
99
+
100
+ public function view_list( $id ) {
101
+ global $wpdb;
102
+
103
+ $emails = ES_DB_Sending_Queue::get_emails_by_hash( $id );
104
+ $email_viewed_count = ES_DB_Sending_Queue::get_viewed_count_by_hash( $id );
105
+ $total_email_sent = ES_DB_Sending_Queue::get_total_email_count_by_hash( $id );
106
+
107
+ ?>
108
+ <div class="wrap">
109
+ <div class="tool-box">
110
+ <div class="tablenav">
111
+ <div class="alignleft" style="padding-bottom:10px;"><?php echo 'Viewed ' . $email_viewed_count . '/' . $total_email_sent; ?></div>
112
+ </div>
113
+ <form name="frm_es_display" method="post">
114
+ <table width="100%" class="widefat" id="straymanage">
115
+ <thead>
116
+ <?php echo $this->prepare_header_footer_row(); ?>
117
+ </thead>
118
+ <tbody>
119
+ <?php echo $this->prepare_body( $emails ); ?>
120
+ </tbody>
121
+ <tfoot>
122
+ <?php echo $this->prepare_header_footer_row(); ?>
123
+ </tfoot>
124
+ </table>
125
+ </form>
126
+ </div>
127
+ </div>
128
+
129
+ <?php
130
+
131
+ //$wpdb->update( EMAIL_SUBSCRIBERS_STATS_TABLE, array( 'viewdate' => date( 'Y-m-d H:i:s' ) ), array( 'viewdate' => $id ) );
132
+
133
+ }
134
+
135
+
136
+ public function prepare_body( $emails ) {
137
+
138
+ $i = 1;
139
+ foreach ( $emails as $key => $email ) {
140
+ $class = '';
141
+ if ( $i % 2 === 0 ) {
142
+ $class = 'alternate';
143
+ }
144
+
145
+ $email_id = ! empty( $email['email'] ) ? $email['email'] : ( ! empty( $email['es_deliver_emailmail'] ) ? $email['es_deliver_emailmail'] : '' );
146
+ $status = ! empty( $email['status'] ) ? $email['status'] : ( ! empty( $email['es_deliver_sentstatus'] ) ? $email['es_deliver_sentstatus'] : '' );
147
+ $sent_at = ! empty( $email['sent_at'] ) ? $email['sent_at'] : ( ! empty( $email['es_deliver_sentdate'] ) ? $email['es_deliver_sentdate'] : '' );
148
+ $opened = ! empty( $email['opened'] ) ? $email['opened'] : ( ! empty( $email['es_deliver_status'] ) && $email['es_deliver_status'] === 'Viewed' ? 1 : 0 );
149
+ $opened_at = ! empty( $email['opened_at'] ) ? $email['opened_at'] : ( ! empty( $email['es_deliver_viewdate'] ) ? $email['es_deliver_viewdate'] : '' );
150
+
151
+ ?>
152
+
153
+ <tr class="<?php echo $class; ?>">
154
+ <td align="left"><?php echo $i; ?></td>
155
+ <td><?php echo $email_id; ?></td>
156
+ <td><span style="color:#03a025;font-weight:bold;"><?php echo $status; ?></span></td>
157
+ <td><?php echo ig_es_format_date_time( $sent_at ); ?></td>
158
+ <td><span><?php echo ( ! empty( $opened ) && $opened == 1 ) ? _e( 'Viewed', 'email-subscribers' ) : '<i title="' . __( 'Not yet viewed', 'email-subscribers' ) . '" class="dashicons dashicons-es dashicons-minus">' ?></span></td>
159
+ <td><?php echo ig_es_format_date_time( $opened_at ); ?></td>
160
+ </tr>
161
+
162
+ <?php
163
+ $i ++;
164
+ }
165
+
166
+ }
167
+
168
+
169
+ /** Text displayed when no list data is available */
170
+ public function no_items() {
171
+ _e( 'No Reports avaliable.', 'email-subscribers' );
172
+ }
173
+
174
+ /**
175
+ * Render a column when no column specific method exist.
176
+ *
177
+ * @param array $item
178
+ * @param string $column_name
179
+ *
180
+ * @return mixed
181
+ */
182
+ public function column_default( $item, $column_name ) {
183
+ global $wpdb;
184
+
185
+ switch ( $column_name ) {
186
+ case 'start_at':
187
+ case 'finish_at':
188
+ return ig_es_format_date_time( $item[ $column_name ] );
189
+ case 'type':
190
+ if ( empty( $item['campaign_id'] ) ) {
191
+ $type = __( 'Post Notification', 'email-subscribers' );
192
+ } else {
193
+ $type = ES()->campaigns_db->get_campaign_type_by_id( $item['campaign_id'] );
194
+ $type = strtolower( $type );
195
+ $type = ( 'newsletter' === $type ) ? __( 'Broadcast', 'email-subscribers' ) : $type;
196
+ }
197
+
198
+ $type = ucwords( str_replace( '_', ' ', $type ) );
199
+
200
+ return $type;
201
+ case 'subject':
202
+ // case 'type':
203
+ // return ucwords($item[ $column_name ]);
204
+ case 'count':
205
+ return $item[ $column_name ];
206
+ default:
207
+ return print_r( $item, true ); //Show the whole array for troubleshooting purposes
208
+ }
209
+ }
210
+
211
+ function column_status( $item ) {
212
+ if ( $item['status'] == 'Sent' ) {
213
+ return __( 'Completed', 'email-subscribers' );
214
+ } else {
215
+
216
+ $actions = array(
217
+ 'send_now' => $this->prepare_send_now_url( $item )
218
+ );
219
+
220
+ return $item['status'] . $this->row_actions( $actions, true );
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Render the bulk edit checkbox
226
+ *
227
+ * @param array $item
228
+ *
229
+ * @return string
230
+ */
231
+ function column_cb( $item ) {
232
+ return sprintf(
233
+ '<input type="checkbox" name="bulk_delete[]" value="%s" />', $item['id']
234
+ );
235
+ }
236
+
237
+
238
+ /**
239
+ * Method for name column
240
+ *
241
+ * @param array $item an array of DB data
242
+ *
243
+ * @return string
244
+ */
245
+ function column_subject( $item ) {
246
+
247
+ $es_nonce = wp_create_nonce( 'es_notification' );
248
+ $page = ig_es_get_request_data( 'page' );
249
+
250
+ $title = '<strong>' . $item['subject'] . '</strong>';
251
+
252
+ $actions = array(
253
+ 'view' => sprintf( '<a href="?page=%s&action=%s&list=%s&_wpnonce=%s">%s</a>', esc_attr( $page ), 'view', $item['hash'], $es_nonce, __( 'View', 'email-subscribers' ) ),
254
+ 'delete' => sprintf( '<a href="?page=%s&action=%s&list=%s&_wpnonce=%s">%s</a>', esc_attr( $page ), 'delete', absint( $item['id'] ), $es_nonce, __( 'Delete', 'email-subscribers' ) ),
255
+ 'preview_email' => sprintf( '<a target="_blank" href="?page=%s&action=%s&list=%s&_wpnonce=%s">%s</a>', esc_attr( $page ), 'preview', absint( $item['id'] ), $es_nonce, __( 'Preview', 'email-subscribers' ) )
256
+ );
257
+
258
+ return $title . $this->row_actions( $actions );
259
+ }
260
+
261
+
262
+ /**
263
+ * Associative array of columns
264
+ *
265
+ * @return array
266
+ */
267
+ function get_columns() {
268
+ $columns = array(
269
+ 'cb' => '<input type="checkbox" />',
270
+ 'subject' => __( 'Subject', 'email-subscribers' ),
271
+ 'type' => __( 'Type', 'email-subscribers' ),
272
+ 'status' => __( 'Status', 'email-subscribers' ),
273
+ 'start_at' => __( 'Start Date', 'email-subscribers' ),
274
+ 'finish_at' => __( 'End Date', 'email-subscribers' ),
275
+ 'count' => __( 'Total Contacts', 'email-subscribers' ),
276
+ );
277
+
278
+ return $columns;
279
+ }
280
+
281
+ function column_count( $item ) {
282
+
283
+ $campaign_hash = $item['hash'];
284
+
285
+ $total_emails_sent = $total_emails_to_be_sent = $item['count'];
286
+ // if ( ! empty( $campaign_hash ) ) {
287
+ // $total_emails_sent = ES_DB_Sending_Queue::get_total_emails_sent_by_hash( $campaign_hash );
288
+ // }
289
+
290
+ // $content = $total_emails_sent . "/" . $total_emails_to_be_sent;
291
+
292
+ return $total_emails_to_be_sent;
293
+
294
+ }
295
+
296
+ function prepare_send_now_url( $item ) {
297
+ $campaign_hash = $item['hash'];
298
+
299
+ $cron_url = '';
300
+ if ( ! empty( $campaign_hash ) ) {
301
+ $cron_url = ES()->cron->url( true, false, $campaign_hash );
302
+ }
303
+
304
+
305
+ $content = '';
306
+ if ( ! empty( $cron_url ) ) {
307
+ $content = __( sprintf( "<a href='%s' target='_blank'>Send</a>", $cron_url ), 'email-subscribers' );
308
+ }
309
+
310
+ return $content;
311
+ }
312
+
313
+ /**
314
+ * Columns to make sortable.
315
+ *
316
+ * @return array
317
+ */
318
+ public function get_sortable_columns() {
319
+ $sortable_columns = array(
320
+ 'subject' => array( 'subject', true ),
321
+ 'status' => array( 'status', true ),
322
+ 'start_at' => array( 'start_at', true ),
323
+ 'finish_at' => array( 'finish_at', true ),
324
+ 'count' => array( 'count', true )
325
+ );
326
+
327
+ return $sortable_columns;
328
+ }
329
+
330
+ /**
331
+ * Returns an associative array containing the bulk action
332
+ *
333
+ * @return array
334
+ */
335
+ public function get_bulk_actions() {
336
+ $actions = array(
337
+ 'bulk_delete' => __( 'Delete', 'email-subscribers' )
338
+ );
339
+
340
+ return $actions;
341
+ }
342
+
343
+
344
+ /**
345
+ * Handles data query and filter, sorting, and pagination.
346
+ */
347
+ public function prepare_items() {
348
+
349
+ $this->_column_headers = $this->get_column_info();
350
+
351
+ /** Process bulk action */
352
+ $this->process_bulk_action();
353
+
354
+ $per_page = $this->get_items_per_page( 'reports_per_page', 20 );
355
+ $current_page = $this->get_pagenum();
356
+ $total_items = $this->get_notifications( 0, 0, true );
357
+
358
+ $this->set_pagination_args( array(
359
+ 'total_items' => $total_items, //WE have to calculate the total number of items
360
+ 'per_page' => $per_page //WE have to determine how many items to show on a page
361
+ ) );
362
+
363
+ $this->items = $this->get_notifications( $per_page, $current_page, false );
364
+ }
365
+
366
+ public function get_notifications( $per_page = 5, $page_number = 1, $do_count_only = false ) {
367
+ global $wpdb;
368
+
369
+ $order_by = sanitize_sql_orderby( ig_es_get_request_data( 'orderby' ) );
370
+ $order = ig_es_get_request_data( 'order' );
371
+
372
+ $ig_mailing_queue_table = IG_MAILING_QUEUE_TABLE;
373
+
374
+ if ( $do_count_only ) {
375
+ $sql = "SELECT count(*) as total FROM {$ig_mailing_queue_table}";
376
+ } else {
377
+ $sql = "SELECT * FROM {$ig_mailing_queue_table}";
378
+ }
379
+
380
+ if ( ! $do_count_only ) {
381
+
382
+ // Prepare Order by clause
383
+ $order = ! empty( $order ) ? strtolower( $order ) : 'desc';
384
+
385
+ $expected_order_values = array( 'asc', 'desc' );
386
+ if ( ! in_array( $order, $expected_order_values ) ) {
387
+ $order = 'desc';
388
+ }
389
+
390
+ $default_order_by = esc_sql( 'created_at' );
391
+
392
+ $expected_order_by_values = array( 'subject', 'type', 'status', 'start_at', 'count', 'created_at' );
393
+
394
+ if ( ! in_array( $order_by, $expected_order_by_values ) ) {
395
+ $order_by_clause = " ORDER BY {$default_order_by} DESC";
396
+ } else {
397
+ $order_by = esc_sql( $order_by );
398
+ $order_by_clause = " ORDER BY {$order_by} {$order}, {$default_order_by} DESC";
399
+ }
400
+
401
+ $sql .= $order_by_clause;
402
+ $sql .= " LIMIT $per_page";
403
+ $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
404
+ $result = $wpdb->get_results( $sql, 'ARRAY_A' );
405
+
406
+ } else {
407
+ $result = $wpdb->get_var( $sql );
408
+ }
409
+
410
+ return $result;
411
+ }
412
+
413
+ public function process_bulk_action() {
414
+
415
+ //Detect when a bulk action is being triggered...
416
+ if ( 'view' === $this->current_action() ) {
417
+
418
+ // In our file that handles the request, verify the nonce.
419
+ $nonce = ig_es_get_request_data( '_wpnonce' );
420
+
421
+ if ( ! wp_verify_nonce( $nonce, 'es_notification' ) ) {
422
+ $message = __( 'You do not have permission to view notification', 'email-subscribers' );
423
+ ES_Common::show_message( $message, 'error' );
424
+ } else {
425
+ $this->view_list( ig_es_get_request_data( 'list' ) );
426
+ }
427
+
428
+ } elseif ( 'delete' === $this->current_action() ) {
429
+
430
+ // In our file that handles the request, verify the nonce.
431
+ $nonce = ig_es_get_request_data( '_wpnonce' );
432
+
433
+ if ( ! wp_verify_nonce( $nonce, 'es_notification' ) ) {
434
+ $message = __( 'You do not have permission to delete notification', 'email-subscribers' );
435
+ ES_Common::show_message( $message, 'error' );
436
+ } else {
437
+ $notification_ids = absint( ig_es_get_request_data( 'list' ) );
438
+ ES_DB_Mailing_Queue::delete_notifications( array( $notification_ids ) );
439
+ ES_DB_Sending_Queue::delete_sending_queue_by_mailing_id( array( $notification_ids ) );
440
+ $message = __( 'Report has been deleted successfully!', 'email-subscribers' );
441
+ ES_Common::show_message( $message, 'success' );
442
+ }
443
+
444
+ } elseif ( 'preview' === $this->current_action() ) {
445
+ // In our file that handles the request, verify the nonce.
446
+ $nonce = ig_es_get_request_data( '_wpnonce' );
447
+
448
+ if ( ! wp_verify_nonce( $nonce, 'es_notification' ) ) {
449
+ $message = __( 'You do not have permission to preview notification', 'email-subscribers' );
450
+ ES_Common::show_message( $message, 'error' );
451
+ } else {
452
+ $report_id = ig_es_get_request_data( 'list' );
453
+ echo $this->preview_email( $report_id );
454
+ die();
455
+ }
456
+ }
457
+
458
+ $action = ig_es_get_request_data( 'action' );
459
+ $action2 = ig_es_get_request_data( 'action2' );
460
+ // If the delete bulk action is triggered
461
+ if ( ( 'bulk_delete' === $action ) || ( 'bulk_delete' === $action2 ) ) {
462
+ $notification_ids = ig_es_get_request_data( 'bulk_delete' );
463
+
464
+ if ( count( $notification_ids ) > 0 ) {
465
+ ES_DB_Mailing_Queue::delete_notifications( $notification_ids );
466
+ ES_DB_Sending_Queue::delete_sending_queue_by_mailing_id( $notification_ids );
467
+ $message = __( 'Reports have been deleted successfully!', 'email-subscribers' );
468
+ ES_Common::show_message( $message, 'success' );
469
+ }
470
+
471
+ }
472
+ }
473
+
474
+ public function preview_email( $report_id ) {
475
+ ob_start();
476
+ ?>
477
+ <div class="wrap">
478
+ <h2 style="margin-bottom:1em;">
479
+ <?php echo __( 'Preview Email', 'email-subscribers' ); ?>
480
+ </h2>
481
+ <p>
482
+ <?php echo __( 'This is how the email you sent may look. <br>Note: Different email services (like gmail, yahoo etc) display email content differently. So there could be a slight variation on how your customer will view the email content.', 'email-subscribers' ); ?>
483
+ </p>
484
+ <div class="tool-box">
485
+ <div style="padding:15px;background-color:#FFFFFF;">
486
+ <?php
487
+ $preview = array();
488
+ $preview = ES_DB_Mailing_Queue::get_email_by_id( $report_id );
489
+
490
+ $es_email_type = get_option( 'ig_es_email_type' ); // Not the ideal way. Email type can differ while previewing sent email.
491
+
492
+ if ( $es_email_type == "WP HTML MAIL" || $es_email_type == "PHP HTML MAIL" ) {
493
+ $preview['body'] = ES_Common::es_process_template_body( $preview['body'] );
494
+ } else {
495
+ $preview['body'] = str_replace( "<br />", "\r\n", $preview['body'] );
496
+ $preview['body'] = str_replace( "<br>", "\r\n", $preview['body'] );
497
+ }
498
+
499
+ echo stripslashes( $preview['body'] );
500
+ ?>
501
+ </div>
502
+ </div>
503
+ </div>
504
+ <?php
505
+ $html = ob_get_clean();
506
+
507
+ return $html;
508
+
509
+ }
510
+
511
+ public static function get_instance() {
512
+ if ( ! isset( self::$instance ) ) {
513
+ self::$instance = new self();
514
+ }
515
+
516
+ return self::$instance;
517
+ }
518
+ }
lite/includes/classes/class-es-subscription-throttling.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ class ES_Subscription_Throttling {
9
+
10
+ static function throttle() {
11
+
12
+ global $wpdb;
13
+
14
+ if ( ! ( is_user_logged_in() && is_super_admin() ) ) {
15
+ $subscriber_ip = ig_es_get_ip();
16
+
17
+ $whitelist_ips = array();
18
+ $whitelist_ips = apply_filters( 'ig_es_whitelist_ips', $whitelist_ips );
19
+
20
+ $blacklist_ips = array();
21
+ $blacklist_ips = apply_filters( 'ig_es_blacklist_ips', $blacklist_ips );
22
+
23
+ if ( ! ( empty( $subscriber_ip ) || ( is_array( $whitelist_ips ) && count( $whitelist_ips ) > 0 && in_array( $subscriber_ip, $whitelist_ips ) ) ) ) {
24
+
25
+ if ( is_array( $blacklist_ips ) && count( $blacklist_ips ) > 0 && in_array( $subscriber_ip, $blacklist_ips ) ) {
26
+ return MINUTE_IN_SECONDS * 10;
27
+ }
28
+
29
+ $query = "SELECT count(*) as count from " . IG_CONTACTS_IPS_TABLE . " WHERE ip = %s AND ( `created_on` >= NOW() - INTERVAL %s SECOND )";
30
+ $subscribers = $wpdb->get_var( $wpdb->prepare( $query, $subscriber_ip, DAY_IN_SECONDS ) );
31
+
32
+ if ( $subscribers > 0 ) {
33
+ $timeout = MINUTE_IN_SECONDS * pow( 2, $subscribers - 1 );
34
+
35
+ $query = "SELECT count(*) as count from " . IG_CONTACTS_IPS_TABLE . " WHERE ip = %s AND ( `created_on` >= NOW() - INTERVAL %s SECOND ) LIMIT 1";
36
+ $subscribers = $wpdb->get_var( $wpdb->prepare( $query, $subscriber_ip, $timeout ) );
37
+
38
+ if ( $subscribers > 0 ) {
39
+ return $timeout;
40
+ }
41
+ }
42
+
43
+ // Add IP Address.
44
+ $query = "INSERT INTO " . IG_CONTACTS_IPS_TABLE . " (`ip`) VALUES ( %s )";
45
+ $wpdb->query( $wpdb->prepare( $query, $subscriber_ip ) );
46
+
47
+ // Delete older entries
48
+ $query = "DELETE FROM " . IG_CONTACTS_IPS_TABLE . " WHERE (`created_on` < NOW() - INTERVAL %s SECOND )";
49
+ $wpdb->query( $wpdb->prepare( $query, DAY_IN_SECONDS ) );
50
+ }
51
+ }
52
+
53
+ return false;
54
+ }
55
+
56
+ }
lite/includes/classes/class-es-templates-table.php ADDED
@@ -0,0 +1,323 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ class ES_Templates_Table {
9
+
10
+ static $instance;
11
+
12
+ public function __construct() {
13
+ add_action( 'add_meta_boxes', array( $this, 'es_template_meta_box_add' ) );
14
+ add_action( 'save_post', array( $this, 'es_template_meta_save' ), 10, 2 );
15
+ add_action( 'post_submitbox_misc_actions', array( $this, 'preview_button' ) );
16
+ add_filter( 'manage_edit-es_template_columns', array( $this, 'add_new_columns' ), 10, 1 );
17
+ add_action( 'manage_posts_custom_column', array( $this, 'custom_columns' ) );
18
+ add_action( 'admin_footer', array( $this, 'add_custom_button' ) );
19
+ add_action( 'edit_form_after_title', array( $this, 'add_template_type' ) );
20
+ //duplicate template
21
+ add_filter( 'post_row_actions', array( &$this, 'add_message_action' ), 10, 2 );
22
+ add_action( 'admin_init', array( &$this, 'duplicate_message' ), 10, 1 );
23
+ }
24
+
25
+ public function add_template_type() {
26
+ global $post;
27
+ if ( ! ( is_object( $post ) && 'es_template' === $post->post_type ) ) {
28
+ return;
29
+ }
30
+ $values = get_post_custom( $post->ID );
31
+
32
+ $selected = isset( $values['es_template_type'] ) ? esc_attr( $values['es_template_type'][0] ) : '';
33
+ $template_type = array(
34
+ 'newsletter' => __( 'Broadcast', 'email-subscribers' ),
35
+ 'post_notification' => __( 'Post Notification', 'email-subscribers' )
36
+ );
37
+ $template_type = apply_filters( 'es_template_type', $template_type );
38
+ ?>
39
+ <p>
40
+ <label for="es_template_type"><strong><?php _e( 'Select your Email Template Type', 'email-subscirbers' ); ?></strong></label></br>
41
+ <select name="es_template_type" id="es_template_type">
42
+ <?php
43
+ if ( ! empty( $template_type ) ) {
44
+ foreach ( $template_type as $key => $value ) {
45
+ echo "<option value=" . $key . " " . selected( $selected, $key, false ) . ">" . $value . "</option>";
46
+ }
47
+ }
48
+ ?>
49
+
50
+ </select>
51
+ </p>
52
+ <?php
53
+ }
54
+
55
+ public function es_template_meta_box_add() {
56
+ add_meta_box( 'es_template_meta_box', 'Available Keywords', array( $this, 'es_template_type_meta_box' ), 'es_template', 'normal', 'high' );
57
+ }
58
+
59
+ public function es_template_type_meta_box( $post ) {
60
+
61
+ if ( ! ( is_object( $post ) && 'es_template' === $post->post_type ) ) {
62
+ return;
63
+ }
64
+ ?>
65
+ <p id="post_notification">
66
+ <a href="https://www.icegram.com/documentation/es-what-are-the-available-keywords-in-the-post-notifications/?utm_source=es&amp;utm_medium=in_app&amp;utm_campaign=view_docs_help_page" target="_blank"><?php _e( 'Available Keywords', 'email-subscribers' ); ?></a> <?php _e( 'for Post Notification: ', 'email-subsribers' ); ?> {{FIRSTNAME}},
67
+ {{LASTNAME}}, {{NAME}}, {{EMAIL}},
68
+ {{DATE}}, {{POSTTITLE}}, {{POSTIMAGE}}, {{POSTEXCERPT}}, {{POSTDESC}},
69
+ {{POSTAUTHOR}}, {{POSTLINK}}, {{POSTLINK-WITHTITLE}}, {{POSTLINK-ONLY}}, {{POSTFULL}} </p>
70
+ <p id="newsletter">
71
+ <a href="https://www.icegram.com/documentation/es-what-are-the-available-keywords-in-the-newsletters/?utm_source=es&amp;utm_medium=in_app&amp;utm_campaign=view_docs_help_page" target="_blank"><?php _e( 'Available Keywords', 'email-subscribers' ); ?></a> <?php _e( 'for Broadcast:', 'email-subscribers' ); ?> {{FIRSTNAME}}, {{LASTNAME}}, {{NAME}},
72
+ {{EMAIL}} </p>
73
+ <div id="post_digest">
74
+ <span style="font-size: 0.8em; margin-left: 0.3em; padding: 2px; background: #e66060; color: #fff; border-radius: 2px; ">Pro</span>&nbsp;
75
+ <a href="https://www.icegram.com/send-post-digest-using-email-subscribers-plugin/?utm_source=es&amp;utm_medium=in_app&amp;utm_campaign=view_post_digest_post" target="_blank"><?php _e( 'Available Keywords', 'email-subscribers' ); ?></a> <?php _e( 'for Post Digest:', 'email-subscribers' ); ?>
76
+ {{FIRSTNAME}}, {{LASTNAME}}, {{NAME}}<div class="post_digest_block"> {{POSTDIGEST}} <br/><?php _e( 'Any keywords related Post Notification', 'email-subscribers' ); ?> <br/>{{/POSTDIGEST}} </div>
77
+ </div>
78
+ <?php
79
+ }
80
+
81
+ public function es_template_meta_save( $post_id, $post ) {
82
+ if ( empty( $post_id ) || empty( $post ) || empty( $_POST ) ) {
83
+ return;
84
+ }
85
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
86
+ return;
87
+ }
88
+ if ( is_int( wp_is_post_revision( $post ) ) ) {
89
+ return;
90
+ }
91
+ if ( is_int( wp_is_post_autosave( $post ) ) ) {
92
+ return;
93
+ }
94
+ if ( ! current_user_can( 'edit_post', $post_id ) ) {
95
+ return;
96
+ }
97
+ if ( $post->post_type != 'es_template' ) {
98
+ return;
99
+ }
100
+
101
+
102
+ if ( isset( $_POST['es_template_type'] ) ) {
103
+ $es_template_type = ig_es_get_post_data('es_template_type');
104
+ update_post_meta( $post_id, 'es_template_type', esc_attr( $es_template_type ) );
105
+ }
106
+ }
107
+
108
+
109
+ public function preview_button( $post ) {
110
+ if ( is_object( $post ) && 'es_template' === $post->post_type ) {
111
+ $post_id = $post->ID;
112
+ ?>
113
+
114
+ <div class="misc-pub-section">
115
+ <div id="" class="es_preview_button" style="display: block;">
116
+ <a href="<?php echo admin_url(); ?>admin.php?page=es_template_preview&post=<?php echo $post_id; ?>&preview=true&preview_id=<?php echo $post_id ?>" target="_blank" class="button button-primary es_preview"><?php _e( 'Preview Template', 'email-subscribers' ); ?></a>
117
+ <div class="clear"></div>
118
+ </div>
119
+ </div>
120
+
121
+ <?php
122
+ }
123
+ }
124
+
125
+ public function add_custom_button() {
126
+ $screen = get_current_screen();
127
+ if ( $screen->post_type == 'es_template' ) {
128
+ ?>
129
+ <script type="text/javascript">
130
+ jQuery('<a href="admin.php?page=es_campaigns" class="page-title-action">Campaigns</a>').insertBefore(".wp-header-end");
131
+ </script>
132
+ <?php
133
+ }
134
+ }
135
+
136
+ public function es_template_preview_callback() {
137
+
138
+ $template_id = ig_es_get_request_data('post');
139
+
140
+ $template = get_post( $template_id, ARRAY_A );
141
+
142
+ if ( $template ) {
143
+ $current_user = wp_get_current_user();
144
+ $username = $current_user->user_login;
145
+ $useremail = $current_user->user_email;
146
+
147
+ $es_template_body = $template['post_content'];
148
+
149
+ $es_template_type = get_post_meta( $template_id, 'es_template_type', true );
150
+
151
+
152
+ if ( 'post_notification' === $es_template_type ) {
153
+ $args = array( 'numberposts' => '1', 'order' => 'DESC', 'post_status' => 'publish' );
154
+ $recent_posts = wp_get_recent_posts( $args );
155
+
156
+ if ( count( $recent_posts ) > 0 ) {
157
+ $recent_post = array_shift( $recent_posts );
158
+
159
+ $post_id = $recent_post['ID'];
160
+ $es_template_body = ES_Handle_Post_Notification::prepare_body( $es_template_body, $post_id, $template_id );
161
+ }
162
+ } else {
163
+ $es_template_body = ES_Common::es_process_template_body( $es_template_body, $template_id );
164
+ }
165
+
166
+ $es_template_body = str_replace( '{{NAME}}', $username, $es_template_body );
167
+ $es_template_body = str_replace( '{{EMAIL}}', $useremail, $es_template_body );
168
+
169
+ if ( has_post_thumbnail( $template_id ) ) {
170
+ $image_array = wp_get_attachment_image_src( get_post_thumbnail_id( $template_id ), 'full' );
171
+ $image = '<img src="' . $image_array[0] . '" class="img-responsive" alt="Image for Post ' . $template_id . '" />';
172
+ } else {
173
+ $image = '';
174
+ }
175
+ $html = '';
176
+ $html .= '<style type="text/css">
177
+ .es-sidebar {
178
+ width: 23%;
179
+ background-color: rgb(230, 230, 230);
180
+ padding:15px;
181
+ border-right: 1px solid #bdbdbd;
182
+ }
183
+ .es-preview {
184
+ float: left;
185
+ padding:15px;
186
+ width: 70%;
187
+ background-color:#FFF;
188
+ font-size:16px;
189
+ }
190
+ </style>
191
+ <div class="wrap">
192
+ <div class="tool-box">
193
+ <div class="es-main" style="display:flex;">
194
+ <div class="es-sidebar">
195
+ <h2 style="margin-bottom:1em;">
196
+ Template Preview <a class="add-new-h2" href="' . admin_url() . 'admin.php?page=es-general-information">Help</a>
197
+ </h2>' . Email_Subscribers_Admin::es_feedback() . '
198
+ <p>
199
+ <a class="button-primary" href="' . admin_url() . 'post.php?post=' . $template_id . '&action=edit">Edit</a>
200
+ </p>
201
+ <p>
202
+ This is how your email may look.<br><br>Note: Different email services (like gmail, yahoo etc) display email content differently. So there could be a slight variation on how your customer will view the email content. </p>
203
+ </div>
204
+ <div class="es-preview">' . $es_template_body . '</div>
205
+ <div style="clear:both;"></div>
206
+ </div>
207
+ <div style="clear:both;"></div>
208
+ </div>
209
+ </div>';
210
+ echo apply_filters( 'the_content', $html );
211
+ } else {
212
+ echo 'Please publish it or save it as a draft';
213
+ }
214
+
215
+ }
216
+
217
+ public function add_new_columns( $existing_columns ) {
218
+
219
+ $date = $existing_columns['date'];
220
+ unset( $existing_columns['date'] );
221
+
222
+ $existing_columns['es_template_type'] = __( 'Template Type', 'email-subscribers' );
223
+ $existing_columns['es_template_thumbnail'] = __( 'Thumbnail', 'email-subscribers' );
224
+ $existing_columns['date'] = $date;
225
+
226
+ return $existing_columns;
227
+
228
+ }
229
+
230
+ public function custom_columns( $column ) {
231
+
232
+ global $post;
233
+
234
+ $es_template_thumbnail = get_the_post_thumbnail( $post->ID, array( '200', '200' ) );
235
+ $default_template_thumbnail = '<img src="' . ES_PLUGIN_URL . 'lite/admin/images/envelope.png" />';
236
+ $es_template_thumbnail = apply_filters( 'ig_es_template_thumbnail', $es_template_thumbnail );
237
+ $es_template_thumbnail = ( ! empty( $es_template_thumbnail ) ) ? $es_template_thumbnail : $default_template_thumbnail;
238
+ switch ( $column ) {
239
+ case 'es_template_type':
240
+ $type = get_post_meta( $post->ID, 'es_template_type', true );
241
+ $type = sanitize_text_field(strtolower( $type ));
242
+ $type = ( 'newsletter' === $type ) ? __( 'Broadcast', 'email-subscribers' ) : $type;
243
+ echo $type = ucwords( str_replace( '_', ' ', $type ) );
244
+ break;
245
+ case 'es_template_thumbnail' :
246
+ echo $es_template_thumbnail;
247
+ break;
248
+ default:
249
+ break;
250
+ }
251
+
252
+ return $column;
253
+ }
254
+
255
+ function add_message_action( $actions, $post ) {
256
+ if ( $post->post_type != 'es_template' ) {
257
+ return $actions;
258
+ }
259
+ $actions['duplicate_template'] = '<a class="es-duplicate-template" href="post.php?template_id=' . $post->ID . '&action=duplicate-template" >' . __( 'Duplicate', 'email-subscribers' ) . '</a>';
260
+
261
+ return $actions;
262
+ }
263
+
264
+ function duplicate_message() {
265
+ $action = ig_es_get_request_data( 'action' );
266
+ $template_id = ig_es_get_request_data( 'template_id' );
267
+ if ( ! empty( $template_id ) && 'duplicate-template' === $action ) {
268
+ //duplicate tempalte
269
+ $this->duplicate_in_db( $template_id );
270
+ // $location = admin_url( 'post.php?post='.$duplicate_template_id.'&action=edit');
271
+ $location = admin_url( 'edit.php?post_type=es_template' );
272
+ wp_safe_redirect( $location );
273
+ exit;
274
+ }
275
+ }
276
+
277
+ function duplicate_in_db( $original_id ) {
278
+ // Get access to the database
279
+ global $wpdb;
280
+ // Get the post as an array
281
+ $duplicate = get_post( $original_id, 'ARRAY_A' );
282
+ // Modify some of the elements
283
+ $duplicate['post_title'] = $duplicate['post_title'] . ' ' . __( 'Copy', 'icegram' );
284
+ $duplicate['post_status'] = 'draft';
285
+ // Set the post date
286
+ $timestamp = current_time( 'timestamp', 0 );
287
+
288
+ $duplicate['post_date'] = date( 'Y-m-d H:i:s', $timestamp );
289
+
290
+ // Remove some of the keys
291
+ unset( $duplicate['ID'] );
292
+ unset( $duplicate['guid'] );
293
+ unset( $duplicate['comment_count'] );
294
+
295
+ // Insert the post into the database
296
+ $duplicate_id = wp_insert_post( $duplicate );
297
+
298
+ // Duplicate all taxonomies/terms
299
+ $taxonomies = get_object_taxonomies( $duplicate['post_type'] );
300
+
301
+ foreach ( $taxonomies as $taxonomy ) {
302
+ $terms = wp_get_post_terms( $original_id, $taxonomy, array( 'fields' => 'names' ) );
303
+ wp_set_object_terms( $duplicate_id, $terms, $taxonomy );
304
+ }
305
+
306
+ // Duplicate all custom fields
307
+ $custom_fields = get_post_custom( $original_id );
308
+ foreach ( $custom_fields as $key => $value ) {
309
+ add_post_meta( $duplicate_id, $key, maybe_unserialize( $value[0] ) );
310
+ }
311
+
312
+ return $duplicate_id;
313
+ }
314
+
315
+ public static function get_instance() {
316
+ if ( ! isset( self::$instance ) ) {
317
+ self::$instance = new self();
318
+ }
319
+
320
+ return self::$instance;
321
+ }
322
+
323
+ }
lite/includes/classes/class-es-tools.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * The admin-specific functionality of the plugin.
10
+ *
11
+ * Admin Settings
12
+ *
13
+ * @package Email_Subscribers
14
+ * @subpackage Email_Subscribers/admin
15
+ * @author Your Name <email@example.com>
16
+ */
17
+ class ES_Tools {
18
+ // class instance
19
+ static $instance;
20
+
21
+ public function __construct() {
22
+ // Allow only to send test email to user who have Settings & Campaigns permission
23
+ $accessible_sub_menus = ES_Common::ig_es_get_accessible_sub_menus();
24
+ if ( defined( 'DOING_AJAX' ) && ( in_array( 'settings', $accessible_sub_menus ) || in_array( 'campaigns', $accessible_sub_menus ) ) ) {
25
+ add_action( 'wp_ajax_es_send_test_email', array( $this, 'send_test_email' ) );
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Send Test Email
31
+ *
32
+ * @since 4.0.0
33
+ * @since 4.3.2 Call ES()->mailer->send_test_email() method to send test email
34
+ */
35
+ public function send_test_email() {
36
+
37
+ $response = array();
38
+
39
+ $email = sanitize_email( ig_es_get_request_data( 'es_test_email' ) );
40
+
41
+ $subject = ig_es_get_request_data( 'subject', '' );
42
+ $content = ig_es_get_request_data( 'content', '' );
43
+
44
+ if ( ! empty( $email ) ) {
45
+
46
+ if ( ! empty( $content ) ) {
47
+ $content = str_replace( "{{EMAIL}}", "User Email", $content );
48
+ $content = str_replace( "{{NAME}}", "Username", $content );
49
+ }
50
+
51
+ $response = ES()->mailer->send_test_email( $email, $subject, $content );
52
+
53
+ if ( $response && $response['status'] === 'SUCCESS' ) {
54
+ $response['message'] = __( 'Email has been sent. Please check your inbox', 'email-subscribers' );
55
+ }
56
+
57
+ }
58
+
59
+ echo json_encode( $response );
60
+ exit;
61
+ }
62
+
63
+ public static function get_instance() {
64
+ if ( ! isset( self::$instance ) ) {
65
+ self::$instance = new self();
66
+ }
67
+
68
+ return self::$instance;
69
+ }
70
+ }
71
+
72
+ ?>
lite/includes/classes/class-es-tracking.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ if ( ! class_exists( 'ES_Tracking' ) ) {
8
+ /**
9
+ * Class ES_Tracking
10
+ *
11
+ * Track Activities like Subscribe, Open, Click, Unsubscribe
12
+ *
13
+ * @since 4.2.0
14
+ */
15
+ class ES_Tracking {
16
+ /**
17
+ * ES_Actions constructor.
18
+ *
19
+ * @since 4.2.0
20
+ */
21
+ public function __construct() {
22
+ add_action( 'init', array( $this, 'init' ), 1 );
23
+ }
24
+
25
+ /**
26
+ * Track user interaction
27
+ *
28
+ * @since 4.2.0
29
+ */
30
+ public function init() {
31
+
32
+ }
33
+
34
+ }
35
+ }
36
+
37
+
38
+
39
+
lite/includes/classes/class-es-widget.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ class ES_Widget extends WP_Widget {
9
+
10
+ function __construct() {
11
+ parent::__construct( 'email_subscriber_widget', __( 'Email Subscribers Widget', 'email-subscribers' ), array( 'description' => __( 'Email Subscribers', 'email-subscribers' ) ) );
12
+ }
13
+
14
+ public function widget( $args, $instance ) {
15
+
16
+ $title = apply_filters( 'widget_title', $instance['title'] );
17
+
18
+ echo $args['before_widget'];
19
+
20
+ if ( ! empty( $title ) ) {
21
+ echo $args['before_title'] . $title . $args['after_title'];
22
+ }
23
+
24
+ $display_name = isset( $instance['display_name'] ) ? esc_attr( $instance['display_name'] ) : '';
25
+ $subscribers_group = isset( $instance['subscribers_group'] ) ? esc_attr( $instance['subscribers_group'] ) : '';
26
+ $desc = isset( $instance['short_desc'] ) ? esc_attr( $instance['short_desc'] ) : '';
27
+
28
+ $name = strtolower( $display_name ) != 'no' ? 'yes' : '';
29
+
30
+ $data['name_visible'] = $name;
31
+ $data['list_visible'] = 'no';
32
+ $data['lists'] = array();
33
+ $data['form_id'] = 0;
34
+ $data['list'] = $subscribers_group;
35
+ $data['desc'] = $desc;
36
+
37
+ ES_Shortcode::render_form( $data );
38
+
39
+ echo $args['after_widget'];
40
+ }
41
+
42
+ public function form( $instance ) {
43
+
44
+ $title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
45
+ $short_desc = isset( $instance['short_desc'] ) ? esc_attr( $instance['short_desc'] ) : '';
46
+ $display_name = isset( $instance['display_name'] ) ? esc_attr( $instance['display_name'] ) : '';
47
+ $subscribers_group = isset( $instance['subscribers_group'] ) ? esc_attr( $instance['subscribers_group'] ) : '';
48
+
49
+ $display_names = array( 'yes' => __( 'Yes', 'email-subscribers' ), 'no' => __( 'No', 'email-subscribers' ) );
50
+
51
+ ?>
52
+
53
+ <p>
54
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Widget Title:' ); ?></label>
55
+ <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
56
+ </p>
57
+ <p>
58
+ <label for="<?php echo $this->get_field_id( 'short_desc' ); ?>"><?php _e( 'Short description' ); ?></label>
59
+ <input class="widefat" id="<?php echo $this->get_field_id( 'short_desc' ); ?>" name="<?php echo $this->get_field_name( 'short_desc' ); ?>" type="text" value="<?php echo esc_attr( $short_desc ); ?>">
60
+ </p>
61
+ <p>
62
+ <label for="widget-email-subscribers-2-es_name"><?php _e( 'Display Name Field' ); ?></label>
63
+ <select id="<?php echo $this->get_field_id( 'display_name' ); ?>" name="<?php echo $this->get_field_name( 'display_name' ); ?>" class="widefat" style="width:100%;">
64
+ <?php foreach ( $display_names as $name ) { ?>
65
+ <option <?php selected( $display_name, $name ); ?> value="<?php echo $name; ?>"><?php echo $name; ?></option>
66
+ <?php } ?>
67
+ </select>
68
+ </p>
69
+ <p>
70
+ <label for="widget-email-subscribers-2-es_group"><?php _e( 'Subscriber List' ); ?></label>
71
+ <select id="<?php echo $this->get_field_id( 'subscribers_group' ); ?>" name="<?php echo $this->get_field_name( 'subscribers_group' ); ?>" class="widefat" style="width:100%;">
72
+ <?php echo ES_Common::prepare_list_dropdown_options( $subscribers_group ); ?>
73
+ </select>
74
+ </p>
75
+ <?php
76
+ }
77
+
78
+ public function update( $new_instance, $old_instance ) {
79
+ $instance = array();
80
+ $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
81
+ $instance['short_desc'] = ( ! empty( $new_instance['short_desc'] ) ) ? strip_tags( $new_instance['short_desc'] ) : '';
82
+ $instance['display_name'] = ( ! empty( $new_instance['display_name'] ) ) ? strip_tags( $new_instance['display_name'] ) : '';
83
+ $instance['subscribers_group'] = ( ! empty( $new_instance['subscribers_group'] ) ) ? strip_tags( $new_instance['subscribers_group'] ) : '';
84
+
85
+ return $instance;
86
+ }
87
+ }
lite/includes/db/class-es-db-actions.php CHANGED
@@ -115,4 +115,32 @@ class ES_DB_Actions extends ES_DB {
115
 
116
  return false;
117
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  }
115
 
116
  return false;
117
  }
118
+
119
+ /**
120
+ * Get total contacts who have clicked links in last $days
121
+ *
122
+ * @param int $days
123
+ *
124
+ * @return string|null
125
+ *
126
+ * @since 4.3.2
127
+ */
128
+ public function get_total_contacts_clicks_links( $days = 0 ) {
129
+ global $wpdb;
130
+
131
+ $ig_actions_table = IG_ACTIONS_TABLE;
132
+
133
+ $query = "SELECT COUNT(DISTINCT(`contact_id`)) FROM $ig_actions_table WHERE `type` = %d";
134
+
135
+ $args[] = IG_LINK_CLICK;
136
+
137
+ if ( 0 != $days ) {
138
+ $days = esc_sql( $days );
139
+ $where = " AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))";
140
+ $query .= $where;
141
+ $args[] = $days;
142
+ }
143
+
144
+ return $wpdb->get_var( $wpdb->prepare( $query, $args ) );
145
+ }
146
  }
lite/includes/db/class-es-db-campaigns.php CHANGED
@@ -143,28 +143,6 @@ class ES_DB_Campaigns extends ES_DB {
143
  }
144
 
145
  return $result;
146
-
147
- /*
148
- $insert = is_null( $id ) ? true : false;
149
- $column_formats = self::get_columns();
150
- $column_defaults = self::get_column_defaults();
151
- $prepared_data = ES_DB::prepare_data( $data, $column_formats, $column_defaults, $insert );
152
-
153
- $campaigns_data = $prepared_data['data'];
154
- $column_formats = $prepared_data['column_formats'];
155
- if ( $insert ) {
156
- $result = $wpdb->insert( IG_CAMPAIGNS_TABLE, $campaigns_data, $column_formats );
157
- if ( $result ) {
158
- return $wpdb->insert_id;
159
- }
160
- } else {
161
- $campaigns_data['updated_at'] = ! empty( $campaigns_data['updated_at'] ) ? $campaigns_data['updated_at'] : ig_get_current_date_time();
162
-
163
- $result = $wpdb->update( IG_CAMPAIGNS_TABLE, $campaigns_data, array( 'id' => $id ), $column_formats );
164
- }
165
- return $result;
166
- */
167
-
168
  }
169
 
170
  /**
@@ -188,10 +166,6 @@ class ES_DB_Campaigns extends ES_DB {
188
  * @since 4.0.0
189
  */
190
  public function migrate_post_notifications() {
191
- /**
192
- * - Migrate post notifications from es_notification table
193
- *
194
- */
195
  global $wpdb;
196
 
197
  $campaigns_data = array();
143
  }
144
 
145
  return $result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  }
147
 
148
  /**
166
  * @since 4.0.0
167
  */
168
  public function migrate_post_notifications() {
 
 
 
 
169
  global $wpdb;
170
 
171
  $campaigns_data = array();
lite/includes/db/class-es-db-contacts.php CHANGED
@@ -157,6 +157,38 @@ class ES_DB_Contacts extends ES_DB {
157
 
158
  }
159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  /**
161
  * Get contact hash by contact id
162
  *
@@ -282,6 +314,15 @@ class ES_DB_Contacts extends ES_DB {
282
 
283
  }
284
 
 
 
 
 
 
 
 
 
 
285
  /**
286
  * Delete Contacts by ids
287
  *
@@ -345,7 +386,7 @@ class ES_DB_Contacts extends ES_DB {
345
  }
346
 
347
  $query = "INSERT INTO $ig_lists_contacts_table (`list_id`, `contact_id`, `status`, `optin_type`, `subscribed_at`, `subscribed_ip` ) VALUES ";
348
- $query .= $this->array_to_str($place_holders);
349
  $sql = $wpdb->prepare( "$query ", $values );
350
  if ( $wpdb->query( $sql ) ) {
351
  return true;
@@ -533,7 +574,7 @@ class ES_DB_Contacts extends ES_DB {
533
  $query = "SELECT id FROM $ig_contacts_table";
534
 
535
  if ( count( $emails ) > 0 ) {
536
- $emails_str = "'".$this->array_to_str( $emails, "', '" ). "'";
537
  $query .= " WHERE email IN ($emails_str)";
538
  }
539
 
@@ -559,9 +600,11 @@ class ES_DB_Contacts extends ES_DB {
559
  $query = "SELECT id, email FROM $ig_contacts_table";
560
 
561
  if ( count( $emails ) > 0 ) {
562
- $emails_str = $this->array_to_str( $emails );
563
- $query .= " WHERE email IN ($emails_str)";
 
564
  }
 
565
  $results = $wpdb->get_results( $query, ARRAY_A );
566
 
567
  $map = array();
@@ -732,11 +775,11 @@ class ES_DB_Contacts extends ES_DB {
732
  public function edit_list_contact_status( $contact_ids, $list_ids, $status ) {
733
  global $wpdb;
734
 
735
- $ids = array_map( 'absint', $contact_ids );
736
- $ids = $this->array_to_str($ids);
737
 
738
  $list_ids = array_map( 'absint', $list_ids );
739
- $list_ids = $this->array_to_str($list_ids);
740
 
741
  $current_date = ig_get_current_date_time();
742
 
@@ -754,6 +797,6 @@ class ES_DB_Contacts extends ES_DB {
754
  }
755
 
756
  return $wpdb->query( $query );
757
-
758
  }
 
759
  }
157
 
158
  }
159
 
160
+ /**
161
+ * Update contact
162
+ *
163
+ * @param int $id
164
+ *
165
+ * @return void
166
+ *
167
+ * @since 4.3.2
168
+ */
169
+ public function update_contact( $contact_id = 0, $data = array() ) {
170
+
171
+ if ( ! empty( $contact_id ) ) {
172
+
173
+ $email = ! empty( $data['email'] ) ? sanitize_email( $data['email'] ) : '';
174
+ if ( ! empty( $email ) ) {
175
+
176
+ $first_name = ! empty( $data['first_name'] ) ? sanitize_text_field( $data['first_name'] ) : '';
177
+ $last_name = ! empty( $data['last_name'] ) ? sanitize_text_field( $data['last_name'] ) : '';
178
+
179
+ $data_to_update = array(
180
+ 'first_name' => $first_name,
181
+ 'last_name' => $last_name,
182
+ 'email' => $email,
183
+ 'updated_at' => ig_get_current_date_time()
184
+ );
185
+
186
+ $this->update( $contact_id, $data_to_update );
187
+ }
188
+ }
189
+
190
+ }
191
+
192
  /**
193
  * Get contact hash by contact id
194
  *
314
 
315
  }
316
 
317
+ /**
318
+ * Get Total Contacts
319
+ *
320
+ * @since 4.3.2
321
+ */
322
+ public function get_total_contacts() {
323
+ return $this->count();
324
+ }
325
+
326
  /**
327
  * Delete Contacts by ids
328
  *
386
  }
387
 
388
  $query = "INSERT INTO $ig_lists_contacts_table (`list_id`, `contact_id`, `status`, `optin_type`, `subscribed_at`, `subscribed_ip` ) VALUES ";
389
+ $query .= $this->array_to_str( $place_holders );
390
  $sql = $wpdb->prepare( "$query ", $values );
391
  if ( $wpdb->query( $sql ) ) {
392
  return true;
574
  $query = "SELECT id FROM $ig_contacts_table";
575
 
576
  if ( count( $emails ) > 0 ) {
577
+ $emails_str = "'" . $this->array_to_str( $emails, "', '" ) . "'";
578
  $query .= " WHERE email IN ($emails_str)";
579
  }
580
 
600
  $query = "SELECT id, email FROM $ig_contacts_table";
601
 
602
  if ( count( $emails ) > 0 ) {
603
+ $emails_str = "'" . $this->array_to_str( $emails, "', '" ) . "'";
604
+
605
+ $query .= " WHERE email IN ($emails_str)";
606
  }
607
+
608
  $results = $wpdb->get_results( $query, ARRAY_A );
609
 
610
  $map = array();
775
  public function edit_list_contact_status( $contact_ids, $list_ids, $status ) {
776
  global $wpdb;
777
 
778
+ $ids = array_map( 'absint', $contact_ids );
779
+ $ids = $this->array_to_str( $ids );
780
 
781
  $list_ids = array_map( 'absint', $list_ids );
782
+ $list_ids = $this->array_to_str( $list_ids );
783
 
784
  $current_date = ig_get_current_date_time();
785
 
797
  }
798
 
799
  return $wpdb->query( $query );
 
800
  }
801
+
802
  }
lite/includes/db/class-es-db-lists-contacts.php CHANGED
@@ -297,12 +297,69 @@ class ES_DB_Lists_Contacts {
297
 
298
  $total = $wpdb->get_var( $query );
299
 
300
- if($total > 0) {
301
  $response = true;
302
  }
303
 
304
  return $response;
305
  }
306
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
 
308
  }
297
 
298
  $total = $wpdb->get_var( $query );
299
 
300
+ if ( $total > 0 ) {
301
  $response = true;
302
  }
303
 
304
  return $response;
305
  }
306
 
307
+ /**
308
+ * Get Total Subscribers count based on timeline
309
+ *
310
+ * @param int $days
311
+ *
312
+ * @return string|null
313
+ *
314
+ * @since 4.3.2
315
+ */
316
+ public static function get_total_subscribed_contacts( $days = 0 ) {
317
+
318
+ global $wpdb;
319
+
320
+ $ig_lists_contacts_table = IG_LISTS_CONTACTS_TABLE;
321
+
322
+ $query = "SELECT COUNT(DISTINCT(`contact_id`)) FROM $ig_lists_contacts_table WHERE `status` = %s ";
323
+
324
+ $args[] = 'subscribed';
325
+
326
+ if ( 0 != $days ) {
327
+ $days = esc_sql( $days );
328
+ $where = " AND subscribed_at >= DATE_SUB(NOW(), INTERVAL %d DAY)";
329
+ $query .= $where;
330
+ $args[] = $days;
331
+ }
332
+
333
+ return $wpdb->get_var( $wpdb->prepare( $query, $args ) );
334
+ }
335
+
336
+ /**
337
+ * Get Total Subscribers count based on timeline
338
+ *
339
+ * @param int $days
340
+ *
341
+ * @return string|null
342
+ *
343
+ * @since 4.3.2
344
+ */
345
+ public static function get_total_unsubscribed_contacts( $days = 0 ) {
346
+
347
+ global $wpdb;
348
+
349
+ $ig_lists_contacts_table = IG_LISTS_CONTACTS_TABLE;
350
+
351
+ $query = "SELECT COUNT(DISTINCT(`contact_id`)) FROM $ig_lists_contacts_table WHERE `status` = %s ";
352
+
353
+ $args[] = 'unsubscribed';
354
+
355
+ if ( 0 != $days ) {
356
+ $days = esc_sql( $days );
357
+ $where = " AND unsubscribed_at >= DATE_SUB(NOW(), INTERVAL %d DAY)";
358
+ $query .= $where;
359
+ $args[] = $days;
360
+ }
361
+
362
+ return $wpdb->get_var( $wpdb->prepare( $query, $args ) );
363
+ }
364
 
365
  }
lite/includes/db/class-es-db-sending-queue.php CHANGED
@@ -61,28 +61,34 @@ class ES_DB_Sending_Queue {
61
  return $subscribers;
62
  }
63
 
64
- public static function update_sent_status( $ids, $status ) {
65
  global $wpdb;
66
 
 
 
 
 
 
67
  $id_str = '';
68
- if ( is_array( $ids ) && count( $ids ) > 0 ) {
69
- $id_str = implode( ",", $ids );
70
- } elseif ( is_string( $ids ) ) {
71
- $id_str = $ids;
72
  }
73
 
74
- $updated = false;
75
  if ( ! empty( $id_str ) ) {
76
  $sql = "UPDATE " . IG_SENDING_QUEUE_TABLE . " SET status = %s";
77
 
78
  if ( 'Sent' === $status ) {
79
  $current_time = ig_get_current_date_time();
80
- $sql .= ", sent_at = '{$current_time}' ";
 
81
  }
82
 
83
- $sql .= " WHERE id IN ($id_str)";
 
 
84
 
85
- $sql = $wpdb->prepare( $sql, $status );
86
  $updated = $wpdb->query( $sql );
87
  }
88
 
@@ -213,9 +219,9 @@ class ES_DB_Sending_Queue {
213
 
214
  $delivery_reports_table = IG_SENDING_QUEUE_TABLE;
215
 
216
- $query = "INSERT INTO $delivery_reports_table (`mailing_queue_id`, `mailing_queue_hash`, `campaign_id`, `contact_id`, `contact_hash`, `email`, `status`, `links`, `opened`, `sent_at`, `opened_at`) VALUES ";
217
- $query .= implode( ', ', $place_holders );
218
- $sql = $wpdb->prepare( "$query ", $values );
219
 
220
  if ( $wpdb->query( $sql ) ) {
221
  return true;
@@ -225,13 +231,13 @@ class ES_DB_Sending_Queue {
225
 
226
  }
227
 
228
- public static function update_viewed_status( $guid, $email ) {
229
  global $wpdb;
230
 
231
  $current_date = ig_get_current_date_time();
232
 
233
- $query = "UPDATE " . IG_SENDING_QUEUE_TABLE . " SET opened_at = '{$current_date}', opened = %d WHERE mailing_queue_hash = %s AND email = %s";
234
- $sql = $wpdb->prepare( $query, 1, $guid, $email );
235
 
236
  return $wpdb->query( $sql );
237
  }
@@ -478,4 +484,33 @@ class ES_DB_Sending_Queue {
478
 
479
  }
480
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  }
61
  return $subscribers;
62
  }
63
 
64
+ public static function update_sent_status( $contact_ids, $message_id = 0, $status = 'Sent' ) {
65
  global $wpdb;
66
 
67
+ $updated = false;
68
+ if ( $message_id == 0 ) {
69
+ return $updated;
70
+ }
71
+
72
  $id_str = '';
73
+ if ( is_array( $contact_ids ) && count( $contact_ids ) > 0 ) {
74
+ $id_str = implode( ",", $contact_ids );
75
+ } elseif ( is_string( $contact_ids ) ) {
76
+ $id_str = $contact_ids;
77
  }
78
 
 
79
  if ( ! empty( $id_str ) ) {
80
  $sql = "UPDATE " . IG_SENDING_QUEUE_TABLE . " SET status = %s";
81
 
82
  if ( 'Sent' === $status ) {
83
  $current_time = ig_get_current_date_time();
84
+
85
+ $sql .= ", sent_at = '{$current_time}' ";
86
  }
87
 
88
+ $sql .= " WHERE mailing_queue_id = %d AND contact_id IN ($id_str)";
89
+
90
+ $sql = $wpdb->prepare( $sql, $status, $message_id );
91
 
 
92
  $updated = $wpdb->query( $sql );
93
  }
94
 
219
 
220
  $delivery_reports_table = IG_SENDING_QUEUE_TABLE;
221
 
222
+ $query = "INSERT INTO $delivery_reports_table (`mailing_queue_id`, `mailing_queue_hash`, `campaign_id`, `contact_id`, `contact_hash`, `email`, `status`, `links`, `opened`, `sent_at`, `opened_at`) VALUES ";
223
+ $query .= implode( ', ', $place_holders );
224
+ $sql = $wpdb->prepare( "$query ", $values );
225
 
226
  if ( $wpdb->query( $sql ) ) {
227
  return true;
231
 
232
  }
233
 
234
+ public static function update_viewed_status( $guid = '', $email = '', $message_id = 0 ) {
235
  global $wpdb;
236
 
237
  $current_date = ig_get_current_date_time();
238
 
239
+ $query = "UPDATE " . IG_SENDING_QUEUE_TABLE . " SET opened_at = %s, opened = %d WHERE (mailing_queue_id = %d OR mailing_queue_hash = %s ) AND email = %s";
240
+ $sql = $wpdb->prepare( $query, $current_date, 1, $message_id, $guid, $email );
241
 
242
  return $wpdb->query( $sql );
243
  }
484
 
485
  }
486
 
487
+ /**
488
+ * Get Total Opened emails count based on $days
489
+ *
490
+ * @param int $days
491
+ *
492
+ * @return string|null
493
+ *
494
+ * @since 4.3.2
495
+ */
496
+ public static function get_total_contacts_opened_emails( $days = 0 ) {
497
+
498
+ global $wpdb;
499
+
500
+ $ig_sending_queue_table = IG_SENDING_QUEUE_TABLE;
501
+
502
+ $query = "SELECT COUNT(DISTINCT(`contact_id`)) FROM $ig_sending_queue_table WHERE `opened` = %d";
503
+
504
+ $args[] = 1;
505
+
506
+ if ( 0 != $days ) {
507
+ $days = esc_sql( $days );
508
+ $where = " AND opened_at >= DATE_SUB(NOW(), INTERVAL %d DAY)";
509
+ $query .= $where;
510
+ $args[] = $days;
511
+ }
512
+
513
+ return $wpdb->get_var( $wpdb->prepare( $query, $args ) );
514
+ }
515
+
516
  }
lite/includes/es-backward.php CHANGED
@@ -76,7 +76,7 @@ class es_cls_dbquery {
76
  ES_DB_Lists_Contacts::delete_list_contacts( $contact_id, $list_ids );
77
  ES_DB_Lists_Contacts::add_lists_contacts( $list_contact_data );
78
 
79
- $list_name = ES_Common::prepare_list_name_by_ids($list_ids);
80
 
81
  // Send Email Notification
82
  $data = array(
@@ -84,7 +84,7 @@ class es_cls_dbquery {
84
  'first_name' => $sub_data['first_name'],
85
  'last_name' => $sub_data['last_name'],
86
  'email' => $email,
87
- 'db_id' => $contact_id,
88
  'guid' => $guid,
89
  'list_name' => $list_name
90
  );
@@ -92,7 +92,7 @@ class es_cls_dbquery {
92
  if ( $optin_type == 1 ) {
93
 
94
  // Send Welcome Email.
95
- ES_Mailer::send_welcome_email($email, $data);
96
 
97
  $list_name = ES()->lists_db->get_list_id_name_map( $list_id );
98
  $template_data = array(
@@ -103,18 +103,13 @@ class es_cls_dbquery {
103
  'list_name' => $list_name
104
  );
105
 
106
- ES_Common::send_signup_notification_to_admins( $template_data );
107
 
108
  } else {
109
-
110
  // Send Confirmation mail
111
- $subject = get_option( 'ig_es_confirmation_mail_subject', __( 'Confirm Your Subscription!', 'email-subscribers' ) );
112
- $content = ES_Mailer::prepare_double_optin_email( $data );
113
-
114
- ES_Mailer::send( $email, $subject, $content );
115
  }
116
 
117
-
118
  }
119
  }
120
 
76
  ES_DB_Lists_Contacts::delete_list_contacts( $contact_id, $list_ids );
77
  ES_DB_Lists_Contacts::add_lists_contacts( $list_contact_data );
78
 
79
+ $list_name = ES_Common::prepare_list_name_by_ids( $list_ids );
80
 
81
  // Send Email Notification
82
  $data = array(
84
  'first_name' => $sub_data['first_name'],
85
  'last_name' => $sub_data['last_name'],
86
  'email' => $email,
87
+ 'contact_id' => $contact_id,
88
  'guid' => $guid,
89
  'list_name' => $list_name
90
  );
92
  if ( $optin_type == 1 ) {
93
 
94
  // Send Welcome Email.
95
+ ES()->mailer->send_welcome_email( $email, $data );
96
 
97
  $list_name = ES()->lists_db->get_list_id_name_map( $list_id );
98
  $template_data = array(
103
  'list_name' => $list_name
104
  );
105
 
106
+ ES()->mailer->send_add_new_contact_notification_to_admins( $template_data );
107
 
108
  } else {
 
109
  // Send Confirmation mail
110
+ ES()->mailer->send_double_optin_email( $email, $data );
 
 
 
111
  }
112
 
 
113
  }
114
  }
115
 
lite/includes/es-core-functions.php CHANGED
@@ -212,6 +212,7 @@ if ( ! function_exists( 'ig_es_get_data' ) ) {
212
  if ( $clean ) {
213
  $value = ig_es_clean( $value );
214
  }
 
215
  return $value;
216
  }
217
  }
212
  if ( $clean ) {
213
  $value = ig_es_clean( $value );
214
  }
215
+
216
  return $value;
217
  }
218
  }
lite/includes/mailers/class-es-base-mailer.php CHANGED
@@ -4,11 +4,98 @@ if ( ! defined( 'ABSPATH' ) ) {
4
  }
5
 
6
  if ( ! class_exists( 'ES_Base_Mailer' ) ) {
7
-
 
 
 
 
8
  class ES_Base_Mailer {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  function __construct() {
11
 
12
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  }
14
  }
4
  }
5
 
6
  if ( ! class_exists( 'ES_Base_Mailer' ) ) {
7
+ /**
8
+ * Class ES_Base_Mailer
9
+ *
10
+ * @since 4.3.2
11
+ */
12
  class ES_Base_Mailer {
13
+ /**
14
+ * @since 4.3.2
15
+ * @var
16
+ *
17
+ */
18
+ var $name;
19
+
20
+ /**
21
+ * @since 4.3.2
22
+ * @var
23
+ *
24
+ */
25
+ var $slug;
26
+
27
+ /**
28
+ * @since 4.3.2
29
+ * @var string
30
+ *
31
+ */
32
+ var $version = '1.0';
33
 
34
+ /**
35
+ * Added Logger Context
36
+ *
37
+ * @since 4.2.0
38
+ * @var array
39
+ *
40
+ */
41
+ public $logger_context = array(
42
+ 'source' => 'ig_es_email_sending'
43
+ );
44
+
45
+ /**
46
+ * ES_Base_Mailer constructor.
47
+ *
48
+ * @since 4.3.2
49
+ */
50
  function __construct() {
51
 
52
  }
53
+
54
+ /**
55
+ * Send Method
56
+ *
57
+ * @since 4.3.2
58
+ */
59
+ function send( ES_Message $message ) {
60
+ return new WP_Error( 'ig_es_email_sending_failed', 'Send Method Not Implemented' );
61
+ }
62
+
63
+ /**
64
+ * Method will be called before email send
65
+ *
66
+ * @since 4.3.2
67
+ */
68
+ function pre_send( ES_Message $message ) {
69
+
70
+ }
71
+
72
+ /**
73
+ * Method will be called after email send
74
+ *
75
+ * @since 4.3.2
76
+ */
77
+ function post_send( ES_Message $message ) {
78
+
79
+ }
80
+
81
+ /**
82
+ * Prepare Response
83
+ *
84
+ * @param string $status
85
+ * @param string $message
86
+ *
87
+ * @return bool|WP_Error
88
+ *
89
+ * @since 4.3.2
90
+ */
91
+ function do_response( $status = 'success', $message = '' ) {
92
+
93
+ if ( 'success' !== $status ) {
94
+ return new WP_Error( 'ig_es_email_sending_failed', $message );
95
+ }
96
+
97
+ return true;
98
+ }
99
+
100
  }
101
  }
lite/includes/mailers/class-es-pepipost-mailer.php CHANGED
@@ -3,34 +3,73 @@ if ( ! defined( 'ABSPATH' ) ) {
3
  exit;
4
  }
5
  if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
6
-
 
 
 
 
 
7
  class ES_Pepipost_Mailer extends ES_Base_Mailer {
 
 
 
 
 
 
 
 
 
 
 
 
8
 
 
 
 
 
 
9
  function __construct() {
 
10
  }
11
 
12
- function send( $response, $data ) {
13
-
14
- $result = array( 'status' => 'SUCCESS' );
15
- //wp remote call
16
- $url = 'https://api.pepipost.com/v2/sendEmail';
17
- $ig_es_mailer_settings = get_option( 'ig_es_mailer_settings' );
18
- $api_key = ! empty( $ig_es_mailer_settings['pepipost']['api_key'] ) ? $ig_es_mailer_settings['pepipost']['api_key'] : '';
19
-
20
- $params = array();
21
- $params['personalizations'][]['recipient'] = ! empty( $data['to_email'] ) ? $data['to_email'] : '';
22
- $params['from']['fromEmail'] = ! empty( $data['sender_email'] ) ? $data['sender_email'] : '';
23
- $params['from']['fromName'] = ! empty( $data['sender_name'] ) ? $data['sender_name'] : '';
24
- $params['subject'] = ! empty( $data['subject'] ) ? $data['subject'] : '';
25
- $params['content'] = ! empty( $data['email_template'] ) ? $data['email_template'] : '';
26
- $headers = array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  'user-agent' => 'APIMATIC 2.0',
28
  'Accept' => 'application/json',
29
  'content-type' => 'application/json; charset=utf-8',
30
- 'api_key' => $api_key
31
  );
32
 
33
- $headers = ! empty( $data['headers'] ) ? array_merge( $headers, explode( "\n", $data['headers'] ) ) : $headers;
34
  $method = 'POST';
35
  $qs = json_encode( $params );
36
 
@@ -44,30 +83,25 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
44
  $options['body'] = $qs;
45
  }
46
 
47
- $response = wp_remote_request( $url, $options );
48
  if ( ! is_wp_error( $response ) ) {
49
  $body = ! empty( $response['body'] ) ? json_decode( $response['body'], true ) : '';
50
 
51
  if ( ! empty( $body ) ) {
52
  if ( 'Success' === $body['message'] ) {
53
- return $result;
54
  } elseif ( ! empty( $body['error_info'] ) ) {
55
- $result = array(
56
- 'status' => 'ERROR',
57
- 'message' => $body['error_info']['error_message']
58
- );
59
  }
60
-
61
  } else {
62
- $result = array(
63
- 'status' => 'ERROR',
64
- 'message' => wp_remote_retrieve_response_message( $response )
65
- );
66
  }
67
  }
68
 
69
- return $result;
70
- }//send
 
 
71
 
72
  }
73
 
3
  exit;
4
  }
5
  if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
6
+ /**
7
+ * Class ES_Pepipost_Mailer
8
+ *
9
+ * @since 4.2.1
10
+ * @since 4.3.2 Modified response
11
+ */
12
  class ES_Pepipost_Mailer extends ES_Base_Mailer {
13
+ /**
14
+ * @since 4.3.2
15
+ * @var string
16
+ *
17
+ */
18
+ var $api_url = 'https://api.pepipost.com/v2/sendEmail';
19
+ /**
20
+ * @since 4.3.2
21
+ * @var string
22
+ *
23
+ */
24
+ var $api_key = '';
25
 
26
+ /**
27
+ * ES_Pepipost_Mailer constructor.
28
+ *
29
+ * @since 4.3.2
30
+ */
31
  function __construct() {
32
+ parent::__construct();
33
  }
34
 
35
+ /**
36
+ * Send Email
37
+ *
38
+ * @param ES_Message $message
39
+ *
40
+ * @return bool|WP_Error
41
+ *
42
+ * @since 4.2.1
43
+ * @since 4.3.2 Modified Response
44
+ */
45
+ function send( ES_Message $message ) {
46
+
47
+ ES()->logger->info( 'Start Sending Email Using Pepipost', $this->logger_context );
48
+
49
+ $ig_es_mailer_settings = get_option( 'ig_es_mailer_settings', array() );
50
+
51
+ $this->api_key = ! empty( $ig_es_mailer_settings['pepipost']['api_key'] ) ? $ig_es_mailer_settings['pepipost']['api_key'] : '';
52
+
53
+ if ( empty( $this->api_key ) ) {
54
+ return $this->do_response( 'error', 'API Key is empty' );
55
+ }
56
+
57
+ $params = array();
58
+
59
+ $params['personalizations'][]['recipient'] = $message->to;
60
+ $params['from']['fromEmail'] = $message->from;
61
+ $params['from']['fromName'] = $message->from_name;
62
+ $params['subject'] = $message->subject;
63
+ $params['content'] = $message->body;
64
+
65
+ $headers = array(
66
  'user-agent' => 'APIMATIC 2.0',
67
  'Accept' => 'application/json',
68
  'content-type' => 'application/json; charset=utf-8',
69
+ 'api_key' => $this->api_key
70
  );
71
 
72
+ $headers = ! empty( $message->headers ) ? array_merge( $headers, $message->headers ) : $headers;
73
  $method = 'POST';
74
  $qs = json_encode( $params );
75
 
83
  $options['body'] = $qs;
84
  }
85
 
86
+ $response = wp_remote_request( $this->api_url, $options );
87
  if ( ! is_wp_error( $response ) ) {
88
  $body = ! empty( $response['body'] ) ? json_decode( $response['body'], true ) : '';
89
 
90
  if ( ! empty( $body ) ) {
91
  if ( 'Success' === $body['message'] ) {
92
+ return $this->do_response( 'success' );
93
  } elseif ( ! empty( $body['error_info'] ) ) {
94
+ return $this->do_response( 'error', $body['error_info']['error_message'] );
 
 
 
95
  }
 
96
  } else {
97
+ $this->do_response( 'error', wp_remote_retrieve_response_message( $response ) );
 
 
 
98
  }
99
  }
100
 
101
+ ES()->logger->info( 'Email Sent Successfully Using Pepipost', $this->logger_context );
102
+
103
+ return $this->do_response( 'success' );
104
+ }
105
 
106
  }
107
 
lite/includes/mailers/class-es-phpmail-mailer.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+ if ( ! class_exists( 'ES_Phpmail_Mailer' ) ) {
6
+ /**
7
+ * Class ES_Phpmail_Mailer
8
+ *
9
+ * @since 4.3.2
10
+ */
11
+ class ES_Phpmail_Mailer extends ES_Base_Mailer {
12
+ /**
13
+ * ES_Phpmail_Mailer constructor.
14
+ *
15
+ * @since 4.3.2
16
+ */
17
+ function __construct() {
18
+ parent::__construct();
19
+ }
20
+
21
+ /**
22
+ * Send Email
23
+ *
24
+ * @param ES_Message $message
25
+ *
26
+ * @return bool|WP_Error
27
+ *
28
+ * @since 4.3.2
29
+ */
30
+ function send( ES_Message $message ) {
31
+
32
+ ES()->logger->info( 'Start Sending Email Using PHP Mail', $this->logger_context );
33
+
34
+ $message->headers[] = "MIME-Version: 1.0";
35
+ $message->headers[] = "X-Mailer: PHP" . phpversion();
36
+
37
+ $headers = implode("\n", $message->headers);
38
+ $send = mail( $message->to, $message->subject, $message->body, $headers );
39
+
40
+ if ( ! $send ) {
41
+ return $this->do_response( 'error', 'Error in Email Sending' );
42
+ }
43
+
44
+ ES()->logger->info( 'Email Sent Successfully Using PHP Mail', $this->logger_context );
45
+
46
+ return $this->do_response( 'success' );
47
+ }
48
+
49
+ }
50
+
51
+ }
lite/includes/mailers/class-es-wpmail-mailer.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+ if ( ! class_exists( 'ES_Wpmail_Mailer' ) ) {
6
+
7
+ class ES_Wpmail_Mailer extends ES_Base_Mailer {
8
+ /**
9
+ * ES_Wpmail_Mailer constructor.
10
+ *
11
+ * @since 4.3.2
12
+ */
13
+ function __construct() {
14
+ parent::__construct();
15
+ }
16
+
17
+ /**
18
+ * @param ES_Message $message
19
+ *
20
+ * @return boolean|WP_Error
21
+ *
22
+ * @since 4.3.2
23
+ */
24
+ function send( ES_Message $message ) {
25
+
26
+ ES()->logger->info( 'Start Sending Email Using WP Mail', $this->logger_context );
27
+
28
+ $send_mail = wp_mail( $message->to, $message->subject, $message->body, $message->headers );
29
+
30
+ if ( ! $send_mail ) {
31
+ global $phpmailer;
32
+
33
+ $message = wp_strip_all_tags( $phpmailer->ErrorInfo );
34
+
35
+ return $this->do_response( 'error', $message );
36
+ }
37
+
38
+ ES()->logger->info( 'Email Sent Successfully Using WP Mail', $this->logger_context );
39
+
40
+ return $this->do_response( 'success' );
41
+ }
42
+
43
+ }
44
+
45
+ }
lite/includes/upgrade/es-update-functions.php CHANGED
@@ -1082,4 +1082,22 @@ function ig_es_update_431_disable_autoload_options() {
1082
  function ig_es_update_431_db_version() {
1083
  ES_Install::update_db_version( '4.3.1' );
1084
  }
1085
- /* --------------------- ES 4.3.1(End)--------------------------- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1082
  function ig_es_update_431_db_version() {
1083
  ES_Install::update_db_version( '4.3.1' );
1084
  }
1085
+ /* --------------------- ES 4.3.1(End)--------------------------- */
1086
+
1087
+ /**
1088
+ * Import Email Templates
1089
+ *
1090
+ * @sicne 4.3.2
1091
+ */
1092
+ function ig_es_update_432_import_bfcm_templates(){
1093
+ ES_Install::load_templates();
1094
+ }
1095
+ /**
1096
+ * Update DB Update history
1097
+ *
1098
+ * @since 4.3.2
1099
+ */
1100
+ function ig_es_update_432_db_version() {
1101
+ ES_Install::update_db_version( '4.3.2' );
1102
+ }
1103
+ /* --------------------- ES 4.3.2(End)--------------------------- */
lite/public/class-email-subscribers-public.php CHANGED
@@ -137,6 +137,7 @@ class Email_Subscribers_Public {
137
  $hash = ig_es_get_request_data( 'hash' );
138
 
139
  if ( ! empty( $hash ) ) {
 
140
  $data = ig_es_decode_request_data( $hash );
141
 
142
  $db_id = ! empty( $data['contact_id'] ) ? (int) $data['contact_id'] : 0;
@@ -177,23 +178,18 @@ class Email_Subscribers_Public {
177
  'first_name' => ! empty( $contact[ $email ] ) ? $contact[ $email ]['first_name'] : '',
178
  'last_name' => ! empty( $contact[ $email ] ) ? $contact[ $email ]['last_name'] : '',
179
  'email' => $email,
180
- 'db_id' => $db_id,
181
  'guid' => $guid
182
  );
183
 
184
- $enable_welcome_email = get_option( 'ig_es_enable_welcome_email', 'no' );
185
-
186
- if ( $enable_welcome_email === 'yes' ) {
187
- $content = ES_Mailer::prepare_welcome_email( $data );
188
- $subject = ES_Mailer::prepare_welcome_email_subject( $data );
189
- ES_Mailer::send( $email, $subject, $content );
190
- }
191
 
192
  $lists = ES()->lists_db->get_all_lists_name_by_contact( $db_id );
193
  $list_name = implode( ", ", $lists );
194
 
195
  $data['list_name'] = $list_name;
196
- ES_Common::send_signup_notification_to_admins( $data );
 
197
  } elseif ( $option === 'unsubscribe' ) {
198
  $unsubscribed = 1;
199
 
@@ -252,7 +248,7 @@ class Email_Subscribers_Public {
252
 
253
  } elseif ( in_array( $option, array( 'viewstatus', 'open' ) ) ) {
254
  if ( ! empty( $guid ) && ! empty( $email ) ) {
255
- ES_DB_Sending_Queue::update_viewed_status( $guid, $email );
256
 
257
  if ( $campaign_id > 0 && $db_id > 0 ) {
258
  do_action( 'ig_es_message_open', $db_id, $message_id, $campaign_id );
137
  $hash = ig_es_get_request_data( 'hash' );
138
 
139
  if ( ! empty( $hash ) ) {
140
+
141
  $data = ig_es_decode_request_data( $hash );
142
 
143
  $db_id = ! empty( $data['contact_id'] ) ? (int) $data['contact_id'] : 0;
178
  'first_name' => ! empty( $contact[ $email ] ) ? $contact[ $email ]['first_name'] : '',
179
  'last_name' => ! empty( $contact[ $email ] ) ? $contact[ $email ]['last_name'] : '',
180
  'email' => $email,
181
+ 'contact_id' => $db_id,
182
  'guid' => $guid
183
  );
184
 
185
+ ES()->mailer->send_welcome_email( $email, $data );
 
 
 
 
 
 
186
 
187
  $lists = ES()->lists_db->get_all_lists_name_by_contact( $db_id );
188
  $list_name = implode( ", ", $lists );
189
 
190
  $data['list_name'] = $list_name;
191
+
192
+ ES()->mailer->send_add_new_contact_notification_to_admins( $data );
193
  } elseif ( $option === 'unsubscribe' ) {
194
  $unsubscribed = 1;
195
 
248
 
249
  } elseif ( in_array( $option, array( 'viewstatus', 'open' ) ) ) {
250
  if ( ! empty( $guid ) && ! empty( $email ) ) {
251
+ ES_DB_Sending_Queue::update_viewed_status( $guid, $email, $message_id );
252
 
253
  if ( $campaign_id > 0 && $db_id > 0 ) {
254
  do_action( 'ig_es_message_open', $db_id, $message_id, $campaign_id );
readme.txt CHANGED
@@ -5,7 +5,7 @@ Author URI: https://www.icegram.com/
5
  Tags: subscription, newsletter, email marketing, post notification, email newsletter form, email signup, email widget, newsletter signup, subscribe, subscription form, bulk emails, signup form, list builder, lead generation, welcome email, contacts
6
  Requires at least: 3.9
7
  Tested up to: 5.3
8
- Stable tag: 4.3.1
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses
11
 
@@ -300,6 +300,16 @@ Refer [here](https://www.icegram.com/documentation/es-faq/).
300
 
301
  == Changelog ==
302
 
 
 
 
 
 
 
 
 
 
 
303
  **4.3.1 (13.11.2019)**
304
 
305
  * New: Delete Form Permanently
5
  Tags: subscription, newsletter, email marketing, post notification, email newsletter form, email signup, email widget, newsletter signup, subscribe, subscription form, bulk emails, signup form, list builder, lead generation, welcome email, contacts
6
  Requires at least: 3.9
7
  Tested up to: 5.3
8
+ Stable tag: 4.3.2
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses
11
 
300
 
301
  == Changelog ==
302
 
303
+ **4.3.2 (20.11.2019)**
304
+
305
+ * New: Added basic reporting like total subscribed, unsubscribed, open in last 60 days in audience dashboard
306
+ * New: Added Pre header in broadcast
307
+ * Update: Clear all cron on deactivation
308
+ * Update: Improve Email Sending
309
+ * Fix: Override of Cron Schedules
310
+ * Fix: email "Sending" issue
311
+ * Fix: Unsubscribe link issue
312
+
313
  **4.3.1 (13.11.2019)**
314
 
315
  * New: Delete Form Permanently