Email Subscribers & Newsletters - Version 4.8.2

Version Description

  • New: Elementor form integration with Email Subscribers and Newsletters

=

Download this release

Release Info

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

Code changes from version 4.8.1 to 4.8.2

Files changed (182) hide show
  1. email-subscribers.php +30 -29
  2. lite/admin/class-email-subscribers-admin.php +158 -162
  3. lite/admin/class-ig-es-campaign-rules.php +64 -68
  4. lite/admin/class-ig-es-onboarding.php +186 -194
  5. lite/admin/partials/dashboard.php +44 -44
  6. lite/admin/partials/help.php +44 -16
  7. lite/admin/partials/onboarding.php +100 -70
  8. lite/includes/class-email-subscribers-activator.php +3 -3
  9. lite/includes/class-email-subscribers-deactivator.php +1 -1
  10. lite/includes/class-email-subscribers-i18n.php +3 -1
  11. lite/includes/class-email-subscribers-loader.php +17 -17
  12. lite/includes/class-email-subscribers-uninstall.php +9 -9
  13. lite/includes/class-email-subscribers.php +105 -124
  14. lite/includes/class-es-common.php +88 -74
  15. lite/includes/class-es-install.php +265 -132
  16. lite/includes/class-ig-logger.php +10 -10
  17. lite/includes/classes/class-es-actions.php +3 -4
  18. lite/includes/classes/class-es-admin-settings.php +54 -54
  19. lite/includes/classes/class-es-browser.php +519 -519
  20. lite/includes/classes/class-es-cache.php +3 -5
  21. lite/includes/classes/class-es-campaign-report.php +77 -79
  22. lite/includes/classes/class-es-campaigns-table.php +20 -20
  23. lite/includes/classes/class-es-contacts-table.php +35 -40
  24. lite/includes/classes/class-es-cron.php +9 -11
  25. lite/includes/classes/class-es-export-subscribers.php +7 -7
  26. lite/includes/classes/class-es-form-widget.php +6 -6
  27. lite/includes/classes/class-es-forms-table.php +69 -60
  28. lite/includes/classes/class-es-geolocation.php +7 -7
  29. lite/includes/classes/class-es-handle-post-notification.php +7 -7
  30. lite/includes/classes/class-es-handle-subscription.php +44 -43
  31. lite/includes/classes/class-es-handle-sync-wp-user.php +9 -9
  32. lite/includes/classes/class-es-ig-redirect.php +7 -7
  33. lite/includes/classes/class-es-import-subscribers.php +119 -122
  34. lite/includes/classes/class-es-info.php +1 -1
  35. lite/includes/classes/class-es-list-table.php +13 -13
  36. lite/includes/classes/class-es-lists-table.php +10 -10
  37. lite/includes/classes/class-es-mailchimp-api.php +6 -6
  38. lite/includes/classes/class-es-mailer.php +69 -71
  39. lite/includes/classes/class-es-message.php +3 -3
  40. lite/includes/classes/class-es-newsletters.php +34 -35
  41. lite/includes/classes/class-es-old-widget.php +3 -3
  42. lite/includes/classes/class-es-post-notifications.php +3 -3
  43. lite/includes/classes/class-es-queue.php +98 -104
  44. lite/includes/classes/class-es-reports-data.php +33 -27
  45. lite/includes/classes/class-es-reports-table.php +49 -35
  46. lite/includes/classes/class-es-templates-table.php +5 -5
  47. lite/includes/classes/class-es-tools.php +3 -3
  48. lite/includes/classes/class-es-widget.php +3 -3
  49. lite/includes/classes/class-ig-es-background-process-helper.php +26 -26
  50. lite/includes/classes/class-ig-es-subscriber-query.php +43 -47
  51. lite/includes/classes/class-ig-es-trial.php +34 -36
  52. lite/includes/classes/class-ig-es-wc-session-tracker.php +21 -22
  53. lite/includes/classes/ig-es-wc-cookies.php +1 -1
  54. lite/includes/compatibilities/elementor/actions/class-es-ig-form-action.php +156 -0
  55. lite/includes/compatibilities/elementor/class-ig-es-compatibility.php +32 -0
  56. lite/includes/db/class-es-db-actions.php +39 -45
  57. lite/includes/db/class-es-db-blocked-emails.php +0 -2
  58. lite/includes/db/class-es-db-campaigns.php +44 -51
  59. lite/includes/db/class-es-db-contacts.php +45 -50
  60. lite/includes/db/class-es-db-forms.php +31 -34
  61. lite/includes/db/class-es-db-links.php +3 -6
  62. lite/includes/db/class-es-db-lists-contacts.php +52 -53
  63. lite/includes/db/class-es-db-lists.php +25 -28
  64. lite/includes/db/class-es-db-mailing-queue.php +48 -41
  65. lite/includes/db/class-es-db-notifications.php +2 -2
  66. lite/includes/db/class-es-db-queue.php +4 -7
  67. lite/includes/db/class-es-db-sending-queue.php +51 -51
  68. lite/includes/db/class-es-db.php +19 -25
  69. lite/includes/db/class-ig-es-db-unsubscribe-feedback.php +5 -9
  70. lite/includes/db/class-ig-es-db-wc-cart.php +8 -8
  71. lite/includes/db/class-ig-es-db-wc-guest.php +8 -8
  72. lite/includes/es-backward.php +2 -3
  73. lite/includes/es-core-functions.php +167 -168
  74. lite/includes/feedback.php +14 -11
  75. lite/includes/feedback/class-ig-feedback.php +246 -241
  76. lite/includes/feedback/class-ig-plugin-usage-tracker.php +48 -45
  77. lite/includes/feedback/class-ig-tracker.php +22 -21
  78. lite/includes/libraries/action-scheduler/action-scheduler.php +2 -2
  79. lite/includes/libraries/action-scheduler/classes/ActionScheduler_ActionClaim.php +3 -3
  80. lite/includes/libraries/action-scheduler/classes/ActionScheduler_ActionFactory.php +30 -30
  81. lite/includes/libraries/action-scheduler/classes/ActionScheduler_AdminView.php +4 -3
  82. lite/includes/libraries/action-scheduler/classes/ActionScheduler_DataController.php +2 -2
  83. lite/includes/libraries/action-scheduler/classes/ActionScheduler_FatalErrorMonitor.php +10 -10
  84. lite/includes/libraries/action-scheduler/classes/ActionScheduler_ListTable.php +36 -31
  85. lite/includes/libraries/action-scheduler/classes/ActionScheduler_LogEntry.php +5 -5
  86. lite/includes/libraries/action-scheduler/classes/ActionScheduler_NullLogEntry.php +1 -1
  87. lite/includes/libraries/action-scheduler/classes/ActionScheduler_OptionLock.php +1 -0
  88. lite/includes/libraries/action-scheduler/classes/ActionScheduler_QueueCleaner.php +29 -23
  89. lite/includes/libraries/action-scheduler/classes/ActionScheduler_QueueRunner.php +7 -6
  90. lite/includes/libraries/action-scheduler/classes/ActionScheduler_Versions.php +13 -13
  91. lite/includes/libraries/action-scheduler/classes/ActionScheduler_WPCommentCleaner.php +15 -3
  92. lite/includes/libraries/action-scheduler/classes/ActionScheduler_wcSystemStatus.php +8 -6
  93. lite/includes/libraries/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_QueueRunner.php +1 -1
  94. lite/includes/libraries/action-scheduler/classes/WP_CLI/Migration_Command.php +103 -61
  95. lite/includes/libraries/action-scheduler/classes/WP_CLI/ProgressBar.php +1 -1
  96. lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler.php +17 -14
  97. lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Abstract_ListTable.php +47 -33
  98. lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Abstract_QueueRunner.php +2 -2
  99. lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Abstract_RecurringSchedule.php +13 -9
  100. lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Abstract_Schedule.php +3 -2
  101. lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Abstract_Schema.php +6 -6
  102. lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Lock.php +2 -2
  103. lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Logger.php +10 -9
  104. lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Store.php +23 -20
  105. lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_TimezoneHelper.php +9 -9
  106. lite/includes/libraries/action-scheduler/classes/actions/ActionScheduler_Action.php +9 -9
  107. lite/includes/libraries/action-scheduler/classes/actions/ActionScheduler_CanceledAction.php +3 -3
  108. lite/includes/libraries/action-scheduler/classes/actions/ActionScheduler_FinishedAction.php +2 -2
  109. lite/includes/libraries/action-scheduler/classes/actions/ActionScheduler_NullAction.php +2 -2
  110. lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_DBLogger.php +14 -10
  111. lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php +121 -114
  112. lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_HybridStore.php +18 -17
  113. lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_wpCommentLogger.php +44 -36
  114. lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php +122 -113
  115. lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostStatusRegistrar.php +1 -0
  116. lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php +24 -23
  117. lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_TaxonomyRegistrar.php +7 -6
  118. lite/includes/libraries/action-scheduler/classes/migration/ActionMigrator.php +2 -2
  119. lite/includes/libraries/action-scheduler/classes/migration/ActionScheduler_DBStoreMigrator.php +5 -5
  120. lite/includes/libraries/action-scheduler/classes/migration/BatchFetcher.php +20 -15
  121. lite/includes/libraries/action-scheduler/classes/migration/DryRun_LogMigrator.php +1 -1
  122. lite/includes/libraries/action-scheduler/classes/migration/Runner.php +11 -8
  123. lite/includes/libraries/action-scheduler/classes/migration/Scheduler.php +2 -2
  124. lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_CanceledSchedule.php +1 -1
  125. lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_CronSchedule.php +11 -8
  126. lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_IntervalSchedule.php +9 -6
  127. lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_NullSchedule.php +1 -0
  128. lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_Schedule.php +2 -2
  129. lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_SimpleSchedule.php +7 -4
  130. lite/includes/libraries/action-scheduler/classes/schema/ActionScheduler_LoggerSchema.php +4 -5
  131. lite/includes/libraries/action-scheduler/classes/schema/ActionScheduler_StoreSchema.php +2 -5
  132. lite/includes/libraries/action-scheduler/deprecated/ActionScheduler_AdminView_Deprecated.php +5 -5
  133. lite/includes/libraries/action-scheduler/deprecated/ActionScheduler_Schedule_Deprecated.php +1 -1
  134. lite/includes/libraries/action-scheduler/deprecated/ActionScheduler_Store_Deprecated.php +1 -0
  135. lite/includes/libraries/action-scheduler/deprecated/functions.php +24 -24
  136. lite/includes/libraries/action-scheduler/functions.php +42 -42
  137. lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression.php +291 -302
  138. lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_AbstractField.php +78 -83
  139. lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_DayOfMonthField.php +74 -78
  140. lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_DayOfWeekField.php +90 -93
  141. lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_FieldFactory.php +43 -44
  142. lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_FieldInterface.php +29 -29
  143. lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_HoursField.php +33 -36
  144. lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_MinutesField.php +25 -28
  145. lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_MonthField.php +50 -43
  146. lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_YearField.php +29 -32
  147. lite/includes/libraries/class-es-html2text.php +28 -28
  148. lite/includes/libraries/wp-js-editor/wp-js-editor.php +52 -52
  149. lite/includes/logs/class-ig-log-handler-interface.php +2 -3
  150. lite/includes/logs/class-ig-log-handler.php +12 -8
  151. lite/includes/logs/class-ig-logger-interface.php +9 -11
  152. lite/includes/logs/log-handlers/class-ig-log-handler-file.php +3 -3
  153. lite/includes/mailers/class-es-base-mailer.php +30 -34
  154. lite/includes/mailers/class-es-pepipost-mailer.php +68 -67
  155. lite/includes/mailers/class-es-phpmail-mailer.php +10 -10
  156. lite/includes/notices/class-es-admin-notices.php +13 -13
  157. lite/includes/notices/views/ig-es-bfcm-offer.php +2 -2
  158. lite/includes/notices/views/ig-es-offer.php +2 -2
  159. lite/includes/notices/views/trial-consent.php +3 -3
  160. lite/includes/notices/views/trial-to-premium-offer.php +9 -9
  161. lite/includes/premium-services-ui/class-ig-es-premium-services-ui.php +32 -32
  162. lite/includes/pro-features.php +403 -381
  163. lite/includes/services/class-es-email-delivery-check.php +2 -3
  164. lite/includes/services/class-es-service-handle-cron-data.php +15 -16
  165. lite/includes/services/class-es-service-process-email-content.php +6 -6
  166. lite/includes/services/class-es-service-spam-score-check.php +5 -5
  167. lite/includes/services/class-es-services.php +13 -16
  168. lite/includes/upgrade/es-update-functions.php +51 -48
  169. lite/includes/workflows/abstracts/class-es-workflow-action.php +6 -6
  170. lite/includes/workflows/abstracts/class-es-workflow-trigger.php +6 -6
  171. lite/includes/workflows/abstracts/class-ig-es-workflow-variable.php +10 -11
  172. lite/includes/workflows/actions/abstracts/class-ig-es-action-send-email-abstract.php +5 -5
  173. lite/includes/workflows/actions/class-es-action-add-to-list.php +5 -5
  174. lite/includes/workflows/actions/class-es-action-delete-contact.php +2 -2
  175. lite/includes/workflows/admin/class-es-workflow-admin-ajax.php +10 -7
  176. lite/includes/workflows/admin/class-es-workflow-admin-edit.php +19 -19
  177. lite/includes/workflows/admin/views/meta-box-trigger.php +10 -10
  178. lite/includes/workflows/admin/views/meta-box-variables.php +2 -2
  179. lite/includes/workflows/admin/views/modal-variable-info.php +4 -4
  180. lite/includes/workflows/class-es-clean.php +1 -1
  181. lite/language.php +1 -0
  182. lite/languages/email-subscribers.pot +329 -326
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.8.1
7
  * Author: Icegram
8
  * Author URI: https://www.icegram.com/
9
  * Requires at least: 3.9
@@ -28,7 +28,7 @@ if ( ! defined( 'WPINC' ) ) {
28
  * Minimum PHP version required for Email Subscribers
29
  *
30
  * @since 4.4.1
31
- *
32
  * @since 4.4.3 Added if not already defined() check.
33
  */
34
  if ( ! defined( 'IG_ES_MIN_PHP_VER' ) ) {
@@ -44,7 +44,6 @@ if ( ! function_exists( 'ig_es_fail_php_version_notice' ) ) {
44
  *
45
  * @return void
46
  * @since 4.4.1
47
- *
48
  */
49
  function ig_es_fail_php_version_notice() {
50
  /* translators: %s: PHP version */
@@ -111,10 +110,14 @@ if ( ! function_exists( 'ig_es_show_upgrade_pro_notice' ) ) {
111
  ?>
112
  <div class="notice notice-error">
113
  <p>
114
- <?php
115
- /* translators: %s: Link to Email Subscribers Premium upgrade */
116
- echo wp_kses_post( 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' ),
117
- '<a href="' . esc_url( $url ) . '" target="_blank">' . __( 'Email Subscribers Premium', 'email-subscribers' ) . '</a>' ) );
 
 
 
 
118
  ?>
119
  </p>
120
  </div>
@@ -158,7 +161,7 @@ if ( 'premium' === $ig_es_plan ) {
158
  * - If It's installed & It's >= 4.3.0 => return
159
  */
160
 
161
- //- If It's installed & It's < 4.3.0 => Show Upgrade Notice
162
  $all_plugins = $ig_es_tracker::get_plugins( 'all', true );
163
 
164
  $es_pro_plugin = 'email-subscribers-premium/email-subscribers-premium.php';
@@ -176,7 +179,6 @@ if ( 'premium' === $ig_es_plan ) {
176
  if ( is_admin() ) {
177
  add_action( 'admin_head', 'ig_es_show_upgrade_pro_notice', PHP_INT_MAX );
178
  }
179
-
180
  } elseif ( $is_pro_active && version_compare( $es_pro_plugin_version, 4.3, '>=' ) ) {
181
  return;
182
  }
@@ -185,7 +187,7 @@ if ( 'premium' === $ig_es_plan ) {
185
  /* ***************************** Initial Compatibility Work (End) ******************* */
186
 
187
  if ( ! defined( 'ES_PLUGIN_VERSION' ) ) {
188
- define( 'ES_PLUGIN_VERSION', '4.8.1' );
189
  }
190
 
191
  // Plugin Folder Path.
@@ -244,17 +246,17 @@ if ( ! function_exists( 'activate_email_subscribers' ) ) {
244
  /**
245
  * The code that runs during plugin activation.
246
  * This action is documented in includes/class-email-subscribers-activator.php
247
- *
248
  * @param bool $network_wide Is plugin being activated on a network.
249
  */
250
  function activate_email_subscribers( $network_wide ) {
251
 
252
  global $wpdb;
253
-
254
  require_once ES_PLUGIN_DIR . 'lite/includes/class-email-subscribers-activator.php';
255
 
256
  if ( is_multisite() && $network_wide ) {
257
-
258
  // Get all active blogs in the network and activate plugin on each one
259
  $blog_ids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE deleted = %d", 0 ) );
260
  foreach ( $blog_ids as $blog_id ) {
@@ -271,18 +273,17 @@ if ( ! function_exists( 'deactivate_email_subscribers' ) ) {
271
  /**
272
  * The code that runs during plugin deactivation.
273
  * This action is documented in includes/class-email-subscribers-deactivator.php
274
- *
275
  * @param bool $network_wide Is plugin being activated on a network.
276
- *
277
  */
278
  function deactivate_email_subscribers( $network_wide ) {
279
 
280
  require_once ES_PLUGIN_DIR . 'lite/includes/class-email-subscribers-deactivator.php';
281
 
282
  if ( is_multisite() && $network_wide ) {
283
-
284
  global $wpdb;
285
-
286
  // Get all active blogs in the network.
287
  $blog_ids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE deleted = %d", 0 ) );
288
  foreach ( $blog_ids as $blog_id ) {
@@ -302,9 +303,9 @@ if ( ! function_exists( 'ig_es_may_activate_on_blog' ) ) {
302
 
303
  /**
304
  * Function to handle new blog(site) creation/activation in WP Multisite
305
- *
306
  * @param int $blog_id Blog ID of new site.
307
- *
308
  * @since 4.4.2
309
  */
310
  function ig_es_may_activate_on_blog( $blog_id ) {
@@ -332,9 +333,9 @@ if ( ! function_exists( 'ig_es_activate_on_blog' ) ) {
332
 
333
  /**
334
  * Function to trigger Email Subscribers' activation code for individual site/blog in a network.
335
- *
336
  * @param int $blog_id Blog ID of newly created site/blog.
337
- *
338
  * @since 4.4.2
339
  */
340
  function ig_es_activate_on_blog( $blog_id ) {
@@ -349,9 +350,9 @@ if ( ! function_exists( 'ig_es_trigger_deactivation_in_multisite' ) ) {
349
 
350
  /**
351
  * Function to trigger Email Subscribers' deactivation code for individual site in a network.
352
- *
353
  * @param int $blog_id Blog ID of newly created site/blog.
354
- *
355
  * @since 4.4.2
356
  */
357
  function ig_es_trigger_deactivation_in_multisite( $blog_id ) {
@@ -380,7 +381,7 @@ add_action( 'admin_init', 'email_subscribers_redirect' );
380
 
381
  if ( ! function_exists( 'email_subscribers_redirect' ) ) {
382
  function email_subscribers_redirect() {
383
-
384
  // Check if it is multisite and the current user is in the network administrative interface. e.g. `/wp-admin/network/`
385
  if ( is_multisite() && is_network_admin() ) {
386
  return;
@@ -403,15 +404,15 @@ if ( ! function_exists( 'es_subbox' ) ) {
403
  */
404
  function es_subbox( $namefield = null, $desc = null, $group = null ) {
405
 
406
- $allowedtags = ig_es_allowed_html_tags_in_esc();
407
- $atts = array(
408
  'namefield' => $namefield,
409
  'desc' => $desc,
410
- 'group' => $group
411
  );
412
  $subscription_shortcode = ES_Shortcode::render_es_subscription_shortcode( $atts );
413
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
414
- echo wp_kses( $subscription_shortcode , $allowedtags );
415
  }
416
  }
417
 
@@ -422,7 +423,7 @@ if ( ! function_exists( 'es_subbox' ) ) {
422
  require ES_PLUGIN_DIR . 'lite/includes/class-email-subscribers.php';
423
 
424
  if ( ! function_exists( 'ES' ) ) {
425
-
426
  /**
427
  * Email Subscribers instance
428
  *
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.8.2
7
  * Author: Icegram
8
  * Author URI: https://www.icegram.com/
9
  * Requires at least: 3.9
28
  * Minimum PHP version required for Email Subscribers
29
  *
30
  * @since 4.4.1
31
+ *
32
  * @since 4.4.3 Added if not already defined() check.
33
  */
34
  if ( ! defined( 'IG_ES_MIN_PHP_VER' ) ) {
44
  *
45
  * @return void
46
  * @since 4.4.1
 
47
  */
48
  function ig_es_fail_php_version_notice() {
49
  /* translators: %s: PHP version */
110
  ?>
111
  <div class="notice notice-error">
112
  <p>
113
+ <?php
114
+ echo wp_kses_post(
115
+ sprintf(
116
+ /* translators: %s: Link to Email Subscribers Premium upgrade */
117
+ __( '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' ),
118
+ '<a href="' . esc_url( $url ) . '" target="_blank">' . __( 'Email Subscribers Premium', 'email-subscribers' ) . '</a>'
119
+ )
120
+ );
121
  ?>
122
  </p>
123
  </div>
161
  * - If It's installed & It's >= 4.3.0 => return
162
  */
163
 
164
+ // - If It's installed & It's < 4.3.0 => Show Upgrade Notice
165
  $all_plugins = $ig_es_tracker::get_plugins( 'all', true );
166
 
167
  $es_pro_plugin = 'email-subscribers-premium/email-subscribers-premium.php';
179
  if ( is_admin() ) {
180
  add_action( 'admin_head', 'ig_es_show_upgrade_pro_notice', PHP_INT_MAX );
181
  }
 
182
  } elseif ( $is_pro_active && version_compare( $es_pro_plugin_version, 4.3, '>=' ) ) {
183
  return;
184
  }
187
  /* ***************************** Initial Compatibility Work (End) ******************* */
188
 
189
  if ( ! defined( 'ES_PLUGIN_VERSION' ) ) {
190
+ define( 'ES_PLUGIN_VERSION', '4.8.2' );
191
  }
192
 
193
  // Plugin Folder Path.
246
  /**
247
  * The code that runs during plugin activation.
248
  * This action is documented in includes/class-email-subscribers-activator.php
249
+ *
250
  * @param bool $network_wide Is plugin being activated on a network.
251
  */
252
  function activate_email_subscribers( $network_wide ) {
253
 
254
  global $wpdb;
255
+
256
  require_once ES_PLUGIN_DIR . 'lite/includes/class-email-subscribers-activator.php';
257
 
258
  if ( is_multisite() && $network_wide ) {
259
+
260
  // Get all active blogs in the network and activate plugin on each one
261
  $blog_ids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE deleted = %d", 0 ) );
262
  foreach ( $blog_ids as $blog_id ) {
273
  /**
274
  * The code that runs during plugin deactivation.
275
  * This action is documented in includes/class-email-subscribers-deactivator.php
276
+ *
277
  * @param bool $network_wide Is plugin being activated on a network.
 
278
  */
279
  function deactivate_email_subscribers( $network_wide ) {
280
 
281
  require_once ES_PLUGIN_DIR . 'lite/includes/class-email-subscribers-deactivator.php';
282
 
283
  if ( is_multisite() && $network_wide ) {
284
+
285
  global $wpdb;
286
+
287
  // Get all active blogs in the network.
288
  $blog_ids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE deleted = %d", 0 ) );
289
  foreach ( $blog_ids as $blog_id ) {
303
 
304
  /**
305
  * Function to handle new blog(site) creation/activation in WP Multisite
306
+ *
307
  * @param int $blog_id Blog ID of new site.
308
+ *
309
  * @since 4.4.2
310
  */
311
  function ig_es_may_activate_on_blog( $blog_id ) {
333
 
334
  /**
335
  * Function to trigger Email Subscribers' activation code for individual site/blog in a network.
336
+ *
337
  * @param int $blog_id Blog ID of newly created site/blog.
338
+ *
339
  * @since 4.4.2
340
  */
341
  function ig_es_activate_on_blog( $blog_id ) {
350
 
351
  /**
352
  * Function to trigger Email Subscribers' deactivation code for individual site in a network.
353
+ *
354
  * @param int $blog_id Blog ID of newly created site/blog.
355
+ *
356
  * @since 4.4.2
357
  */
358
  function ig_es_trigger_deactivation_in_multisite( $blog_id ) {
381
 
382
  if ( ! function_exists( 'email_subscribers_redirect' ) ) {
383
  function email_subscribers_redirect() {
384
+
385
  // Check if it is multisite and the current user is in the network administrative interface. e.g. `/wp-admin/network/`
386
  if ( is_multisite() && is_network_admin() ) {
387
  return;
404
  */
405
  function es_subbox( $namefield = null, $desc = null, $group = null ) {
406
 
407
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
408
+ $atts = array(
409
  'namefield' => $namefield,
410
  'desc' => $desc,
411
+ 'group' => $group,
412
  );
413
  $subscription_shortcode = ES_Shortcode::render_es_subscription_shortcode( $atts );
414
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
415
+ echo wp_kses( $subscription_shortcode, $allowedtags );
416
  }
417
  }
418
 
423
  require ES_PLUGIN_DIR . 'lite/includes/class-email-subscribers.php';
424
 
425
  if ( ! function_exists( 'ES' ) ) {
426
+
427
  /**
428
  * Email Subscribers instance
429
  *
lite/admin/class-email-subscribers-admin.php CHANGED
@@ -50,7 +50,6 @@ class Email_Subscribers_Admin {
50
  * @param string $version The version of this plugin.
51
  *
52
  * @since 4.0
53
- *
54
  */
55
  public function __construct( $email_subscribers, $version ) {
56
 
@@ -60,7 +59,7 @@ class Email_Subscribers_Admin {
60
  // Reorder ES Submenu
61
 
62
  // Commenting out since we are now registering the submenus in the order required. Therefore no need to change the submenu order later on.
63
- //add_filter( 'custom_menu_order', array( $this, 'submenu_order' ) );
64
 
65
  add_action( 'admin_menu', array( $this, 'email_subscribers_admin_menu' ) );
66
  add_action( 'wp_ajax_es_klawoo_subscribe', array( $this, 'klawoo_subscribe' ) );
@@ -71,37 +70,36 @@ class Email_Subscribers_Admin {
71
  add_action( 'wp_ajax_ig_es_toggle_campaign_status', array( $this, 'toggle_campaign_status' ) );
72
 
73
  add_action( 'admin_init', array( $this, 'ob_start' ) );
74
-
75
  add_action( 'init', array( $this, 'save_screen_option' ) );
76
-
77
  // Add spam score ajax action.
78
  add_action( 'wp_ajax_es_get_spam_score', array( &$this, 'get_spam_score' ) );
79
-
80
  // Add send cron data action.
81
  add_action( 'admin_head', array( $this, 'send_cron_data' ) );
82
  add_action( 'ig_es_after_settings_save', array( $this, 'send_cron_data' ) );
83
-
84
-
85
  // Process and add premium service data(Inline CSS, UTM Tracking etc) to template body.
86
- add_filter( 'es_after_process_template_body', array( $this, 'add_premium_services_data') );
87
-
88
  // Filter to add premium service request data.
89
- add_filter( 'ig_es_util_data', array( $this, 'add_util_data') );
90
-
91
  // Filter to check if utm tracking is enabled.
92
- add_filter( 'ig_es_track_utm', array( $this, 'is_utm_tracking_enabled'), 10, 2 );
93
-
94
  // Disable Icegram server cron when plugin is deactivated.
95
  add_action( 'ig_es_plugin_deactivate', array( $this, 'disable_server_cron' ) );
96
-
97
- //add_action( 'admin_init', array( $this, 'ig_es_send_additional_data_for_tracking' ) );
98
-
99
  // Filter to hook custom validation for specific service request.
100
  add_filter( 'ig_es_service_request_custom_validation', array( $this, 'maybe_override_service_validation' ), 10, 2 );
101
 
102
  // Ajax handler for email preview
103
  add_action( 'wp_ajax_ig_es_preview_email_report', array( $this, 'preview_email_in_report' ) );
104
- add_action( 'wp_ajax_ajax_fetch_report_list', array( $this, 'ajax_fetch_report_list_callback'));
105
 
106
  if ( class_exists( 'IG_ES_Premium_Services_UI' ) ) {
107
  IG_ES_Premium_Services_UI::instance();
@@ -171,45 +169,45 @@ class Email_Subscribers_Admin {
171
  'broadcast_subject_empty_message' => __( 'Please add a broadcast subject before saving.', 'email-subscribers' ),
172
  'empty_template_message' => __( 'Please add email body.', 'email-subscribers' ),
173
  'remove_conditions_message' => __( 'Do you really like to remove all conditions?', 'email-subscribers' ),
174
-
175
  // Workflows messages.
176
- 'no_trigger_message' => __( 'Please select a trigger before saving the workflow.', 'email-subscribers' ),
177
- 'no_actions_message' => __( 'Please add some actions before saving the workflow.', 'email-subscribers' ),
178
- 'no_action_selected_message' => __( 'Please select an action that this workflow should perform before saving the workflow.', 'email-subscribers' ),
179
- 'trigger_change_message' => __( 'Changing the trigger will remove existing actions. Do you want to proceed anyway?.', 'email-subscribers' ),
180
- 'placeholder_copied_message' => __( 'Copied!', 'email-subscribers' ),
181
- 'delete_confirmation_message' => __( 'Are you sure?', 'email-subscribers' ),
182
 
183
  // Import subscribers messages.
184
- 'select_status' => esc_html__( 'Please select the status for the importing contacts!', 'email-subscribers' ),
185
- 'select_list' => esc_html__( 'Please select a list for importing contacts!', 'email-subscribers' ),
186
- 'select_email_column' => esc_html__( 'Please select the email address column!', 'email-subscribers' ),
187
- 'prepare_data' => esc_html__( 'Preparing Data', 'email-subscribers' ),
188
  /* translators: %s: Upload progress */
189
- 'uploading' => esc_html__( 'Uploading...%s', 'email-subscribers' ),
190
  /* translators: %s: Import progress */
191
- 'import_contacts' => esc_html__( 'Importing contacts...%s', 'email-subscribers' ),
192
  /* translators: %s: Import failed svg icon */
193
- 'import_failed' => esc_html__( 'Import failed! %s', 'email-subscribers' ),
194
- 'no_windowclose' => esc_html__( 'Please do not close this window until it completes...', 'email-subscribers' ),
195
- 'prepare_import' => esc_html__( 'Preparing Import...', 'email-subscribers' ),
196
  /* translators: 1. Imported contacts count 2. Total contacts count 3. Failed to import count 4. Memory usage */
197
- 'current_stats' => esc_html__( 'Currently %1$s of %2$s imported with %3$s errors. %4$s %5$s memory usage', 'email-subscribers' ),
198
  /* translators: 1 Duplicate found email message */
199
- 'duplicate_emails_found_message'=> __( '%1$s duplicate emails found.', 'email-subscribers' ),
200
  /* translators: %s: Time left in minutes */
201
- 'estimate_time' => esc_html__( 'Estimate time left: %s minutes', 'email-subscribers' ),
202
  /* translators: %s: Next attempt delaly time */
203
- 'continues_in' => esc_html__( 'Continues in %s seconds', 'email-subscribers' ),
204
- 'error_importing' => esc_html__( 'There was a problem during importing contacts. Please check the error logs for more information!', 'email-subscribers' ),
205
- 'confirm_import' => esc_html__( 'Do you really like to import these contacts?', 'email-subscribers' ),
206
  /* translators: %s: Process complete svg icon */
207
- 'import_complete' => esc_html__( 'Import complete! %s', 'email-subscribers' ),
208
- 'onbeforeunloadimport' => esc_html__( 'You are currently importing subscribers! If you leave the page all pending subscribers don\'t get imported!', 'email-subscribers' ),
209
- 'api_verification_success' => esc_html__( 'API is valid. Fetching lists...', 'email-subscribers' ),
210
  'mailchimp_notice_nowindow_close' => esc_html__( 'Fetching contacts from MailChimp...Please do not close this window', 'email-subscribers' ),
211
  ),
212
- 'is_pro' => ES()->is_pro(),
213
  );
214
 
215
  wp_localize_script( $this->email_subscribers, 'ig_es_js_data', $ig_es_js_data );
@@ -228,14 +226,14 @@ class Email_Subscribers_Admin {
228
  */
229
  require_once ES_PLUGIN_DIR . 'lite/includes/libraries/wp-js-editor/wp-js-editor.php';
230
  }
231
-
232
  // Load required html/js for dynamic WordPress editor.
233
  ig_es_wp_js_editor_admin_scripts();
234
 
235
  // Localize additional required data for workflow functionality
236
  $workflows_data = ES_Workflow_Admin_Edit::get_workflow_data();
237
  wp_localize_script( $this->email_subscribers, 'ig_es_workflows_data', $workflows_data );
238
- } else if ( 'es_subscribers' === $get_page ) {
239
 
240
  $action = ig_es_get_request_data( 'action' );
241
  if ( 'import' === $action ) {
@@ -244,20 +242,18 @@ class Email_Subscribers_Admin {
244
  }
245
  }
246
 
247
- //timepicker
248
  wp_register_script( $this->email_subscribers . '-timepicker', plugin_dir_url( __FILE__ ) . 'js/jquery.timepicker.js', array( 'jquery' ), ES_PLUGIN_VERSION, true );
249
  wp_enqueue_script( $this->email_subscribers . '-timepicker' );
250
 
251
-
252
  if ( ! empty( $get_page ) && 'es_dashboard' === $get_page || 'es_reports' === $get_page ) {
253
  wp_enqueue_script( 'frappe-js', 'https://unpkg.com/frappe-charts@1.5.2/dist/frappe-charts.min.iife.js', array( 'jquery' ), $this->version, false );
254
  }
255
-
256
 
257
  }
258
 
259
  public function remove_submenu() {
260
- //remove submenues
261
  ?>
262
  <script type="text/javascript">
263
  jQuery(document).ready(function () {
@@ -269,62 +265,62 @@ class Email_Subscribers_Admin {
269
  </script>
270
  <?php
271
  }
272
-
273
  public function email_subscribers_admin_menu() {
274
-
275
  $accessible_sub_menus = ES_Common::ig_es_get_accessible_sub_menus();
276
-
277
  if ( count( $accessible_sub_menus ) > 0 ) {
278
 
279
  $menu_title = ES()->get_admin_menu_title();
280
 
281
  // This adds the main menu page.
282
  add_menu_page( $menu_title, $menu_title, 'edit_posts', 'es_dashboard', array( $this, 'es_dashboard_callback' ), 'dashicons-email', 30 );
283
-
284
  if ( 'woo' === IG_ES_PLUGIN_PLAN ) {
285
  // Add Icegram submenu under WooCommerce marketing admin menu.
286
  add_submenu_page( 'woocommerce-marketing', $menu_title, $menu_title, 'manage_woocommerce', 'es_dashboard', array( $this, 'es_dashboard_callback' ) );
287
  }
288
-
289
  // Submenu.
290
  add_submenu_page( 'es_dashboard', __( 'Dashboard', 'email-subscribers' ), __( 'Dashboard', 'email-subscribers' ), 'edit_posts', 'es_dashboard', array( $this, 'es_dashboard_callback' ) );
291
  }
292
-
293
  if ( in_array( 'audience', $accessible_sub_menus ) ) {
294
  // Add Contacts Submenu
295
  $hook = add_submenu_page( 'es_dashboard', __( 'Audience', 'email-subscribers' ), __( 'Audience', 'email-subscribers' ), 'edit_posts', 'es_subscribers', array( $this, 'render_contacts' ) );
296
  add_action( "load-$hook", array( 'ES_Contacts_Table', 'screen_options' ) );
297
-
298
  // Add Lists Submenu
299
  $hook = add_submenu_page( 'es_dashboard', __( 'Lists', 'email-subscribers' ), '<span id="ig-es-lists">' . __( 'Lists', 'email-subscribers' ) . '</span>', 'edit_posts', 'es_lists', array( $this, 'render_lists' ) );
300
- //add_action( "load-$hook", array( 'ES_Lists_Table', 'screen_options' ) );
301
  }
302
 
303
  if ( in_array( 'forms', $accessible_sub_menus ) ) {
304
  // Add Forms Submenu
305
  $hook = add_submenu_page( 'es_dashboard', __( 'Forms', 'email-subscribers' ), __( 'Forms', 'email-subscribers' ), 'edit_posts', 'es_forms', array( $this, 'render_forms' ) );
306
- //add_action( "load-$hook", array( 'ES_Forms_Table', 'screen_options' ) );
307
  }
308
-
309
  if ( in_array( 'campaigns', $accessible_sub_menus ) ) {
310
  // Add Campaigns Submenu
311
  $hook = add_submenu_page( 'es_dashboard', __( 'Campaigns', 'email-subscribers' ), __( 'Campaigns', 'email-subscribers' ), 'edit_posts', 'es_campaigns', array( $this, 'render_campaigns' ) );
312
- //add_action( "load-$hook", array( 'ES_Campaigns_Table', 'screen_options' ) );
313
-
314
  // Start-IG-Code.
315
  add_submenu_page( 'es_dashboard', __( 'Post Notifications', 'email-subscribers' ), '<span id="ig-es-post-notifications">' . __( 'Post Notifications', 'email-subscribers' ) . '</span>', 'edit_posts', 'es_notifications', array( $this, 'load_post_notifications' ) );
316
  // End-IG-Code.
317
  add_submenu_page( 'es_dashboard', __( 'Broadcast', 'email-subscribers' ), '<span id="ig-es-broadcast">' . __( 'Broadcast', 'email-subscribers' ) . '</span>', 'edit_posts', 'es_newsletters', array( $this, 'load_newsletters' ) );
318
  add_submenu_page( null, __( 'Template Preview', 'email-subscribers' ), __( 'Template Preview', 'email-subscribers' ), 'edit_posts', 'es_template_preview', array( $this, 'load_preview' ) );
319
-
320
  }
321
-
322
  if ( in_array( 'workflows', $accessible_sub_menus ) ) {
323
 
324
  // Add Workflows Submenu
325
  $hook = add_submenu_page( 'es_dashboard', __( 'Workflows', 'email-subscribers' ), __( 'Workflows', 'email-subscribers' ), 'edit_posts', 'es_workflows', array( $this, 'render_workflows' ) );
326
 
327
- //add_action( "load-$hook", array( 'ES_Workflows_Table', 'screen_options' ) );
328
  add_action( "load-$hook", array( 'ES_Workflow_Admin_Edit', 'register_meta_boxes' ) );
329
  add_action( "admin_footer-$hook", array( 'ES_Workflow_Admin_Edit', 'print_script_in_footer' ) );
330
  add_action( 'admin_init', array( 'ES_Workflow_Admin_Edit', 'maybe_save' ) );
@@ -367,11 +363,11 @@ class Email_Subscribers_Admin {
367
  new ES_Tracking();
368
  }
369
 
370
- /**
371
  * Function for Klawoo's Subscribe form on Help & Info page
372
- *
373
  * @param boolean $return Flag to check return response instead of exiting in the function itself.
374
- */
375
  public static function klawoo_subscribe( $return = false ) {
376
 
377
  // We don't need to do nonce validation in case if the function is being called from other function.
@@ -404,7 +400,7 @@ class Email_Subscribers_Admin {
404
 
405
  $options = array(
406
  'timeout' => 15,
407
- 'method' => $method
408
  );
409
 
410
  if ( 'POST' == $method ) {
@@ -587,10 +583,10 @@ class Email_Subscribers_Admin {
587
 
588
  ksort( $reorder_es_menu );
589
 
590
- //$submenu['es_dashboard'] = $reorder_es_menu;
591
  }
592
 
593
- # Return the new submenu order
594
  return $menu_order;
595
  }
596
 
@@ -611,13 +607,12 @@ class Email_Subscribers_Admin {
611
 
612
  }
613
 
614
- //save skip signup option
615
  public function es_save_onboarding_skip() {
616
 
617
  $es_skip = ig_es_get_request_data( 'es_skip' );
618
  $option_name = ig_es_get_request_data( 'option_name' );
619
 
620
-
621
  if ( '1' == $es_skip && ! empty( $option_name ) ) {
622
  /**
623
  * If user logged in then only save option.
@@ -641,34 +636,34 @@ class Email_Subscribers_Admin {
641
  $conditions = ig_es_get_request_data( 'conditions', array() );
642
  $get_count = ig_es_get_request_data( 'get_count', 'no' );
643
 
644
- if ( 0 == $list_id && empty( $conditions) ) {
645
  return 0;
646
  }
647
 
648
  $response_data = array();
649
-
650
  if ( ! empty( $conditions ) ) {
651
  if ( 'yes' === $get_count ) {
652
- $args = array(
653
  'lists' => $list_id,
654
  'conditions' => $conditions,
655
  'status' => $status,
656
  'return_count' => true,
657
  );
658
- $query = new IG_ES_Subscribers_Query();
659
  $response_data['total'] = $query->run( $args );
660
  }
661
  ob_start();
662
  do_action( 'ig_es_campaign_show_conditions', $conditions );
663
  $response_data['conditions_html'] = ob_get_clean();
664
  } else {
665
- $response_data['total'] = ES()->lists_contacts_db->get_total_count_by_list( $list_id, $status );
666
  }
667
 
668
  if ( ! empty( $response_data['total'] ) ) {
669
  $response_data['total'] = number_format( $response_data['total'] );
670
  }
671
-
672
  die( json_encode( $response_data ) );
673
  }
674
 
@@ -682,7 +677,7 @@ class Email_Subscribers_Admin {
682
  $post_temp_arr = get_post( $template_id );
683
  $result['subject'] = ! empty( $post_temp_arr->post_title ) ? $post_temp_arr->post_title : '';
684
  $result['body'] = ! empty( $post_temp_arr->post_content ) ? $post_temp_arr->post_content : '';
685
- //get meta data of template
686
  // $active_plugins = $ig_es_tracker::get_active_plugins();
687
  if ( ES()->is_starter() ) {
688
  $result['inline_css'] = get_post_meta( $template_id, 'es_custom_css', true );
@@ -696,7 +691,7 @@ class Email_Subscribers_Admin {
696
  * Get Email Subscribers' screen options
697
  *
698
  * @return array
699
- *
700
  * @since 4.5.4
701
  */
702
  public function get_admin_screen_options() {
@@ -899,7 +894,7 @@ class Email_Subscribers_Admin {
899
 
900
  /**
901
  * Method to start output buffering to allows admin screens to make redirects later on.
902
- *
903
  * @since 4.5.2
904
  */
905
  public function ob_start() {
@@ -908,13 +903,13 @@ class Email_Subscribers_Admin {
908
 
909
  /**
910
  * Method to get spam score
911
- *
912
  * @since 4.6.1
913
  */
914
  public function get_spam_score() {
915
 
916
  check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' );
917
-
918
  global $post;
919
 
920
  $response = array(
@@ -922,7 +917,7 @@ class Email_Subscribers_Admin {
922
  'error_message' => __( 'Something went wrong', 'email-subscribers' ),
923
  );
924
 
925
- $admin_email = get_option( 'admin_email' );
926
  if ( ! empty( $_REQUEST['action'] ) && 'es_get_spam_score' == $_REQUEST['action'] ) {
927
 
928
  $sender_data = array();
@@ -951,12 +946,12 @@ class Email_Subscribers_Admin {
951
  $header .= 'Subject:' . $subject . "\n";
952
  }
953
 
954
- $header .= 'Date: ' . gmdate( 'r' ) . "\n";
955
- $header .= 'To: ' . $admin_email . "\n";
956
- $header .= 'Message-ID: <' . $admin_email . ">\n";
957
- $header .= "MIME-Version: 1.0\n";
958
- $data['email'] = $header . $content;
959
- $data['tasks'][] = 'spam-score';
960
 
961
  $spam_score_service = new ES_Service_Spam_Score_Check();
962
  $service_response = $spam_score_service->get_spam_score( $data );
@@ -990,12 +985,12 @@ class Email_Subscribers_Admin {
990
  $from_email = $sender_data['from_email'];
991
  }
992
 
993
- //adding missing from name
994
  if ( empty( $from_name ) ) {
995
  $from_name = get_option( 'ig_es_from_name', true );
996
  }
997
 
998
- //adding missing from email
999
  if ( empty( $from_email ) ) {
1000
  $from_email = get_option( 'ig_es_from_email', true );
1001
  }
@@ -1006,7 +1001,7 @@ class Email_Subscribers_Admin {
1006
  $headers = array(
1007
  "From: \"$sender_name\" <$sender_email>",
1008
  'Return-Path: <' . $sender_email . '>',
1009
- 'Reply-To: "' . $sender_name . '" <' . $sender_email . '>'
1010
  );
1011
 
1012
  if ( in_array( $get_email_type, array( 'php_html_mail', 'php_plaintext_mail' ) ) ) {
@@ -1031,41 +1026,41 @@ class Email_Subscribers_Admin {
1031
  */
1032
  public function send_cron_data( $options = array() ) {
1033
 
1034
- if ( ! ES()->is_es_admin_screen()) {
1035
  return;
1036
  }
1037
-
1038
  $handle_cron_data_service = new ES_Service_Handle_Cron_Data();
1039
-
1040
  // Send cron data to server
1041
  $handle_cron_data_service->handle_es_cron_data( $options );
1042
  }
1043
-
1044
  /**
1045
  * Method to add ES service data(Inline CSS, UTM tracking to links etc) to email content
1046
  *
1047
  * @param array $data
1048
- *
1049
  * @return array $data
1050
- *
1051
  * @since 4.6.2
1052
  */
1053
  public function add_premium_services_data( $data = array() ) {
1054
 
1055
  $process_email_content_service = new ES_Service_Process_Email_Content();
1056
-
1057
  $data = $process_email_content_service->process_email_content( $data );
1058
-
1059
  return $data;
1060
  }
1061
-
1062
  /**
1063
  * Method to add ES service data(Inline CSS, UTM tracking to links etc) to email content
1064
  *
1065
  * @param array $data
1066
- *
1067
  * @return array $data
1068
- *
1069
  * @since 4.6.2
1070
  */
1071
  public function add_util_data( $data = array() ) {
@@ -1078,40 +1073,39 @@ class Email_Subscribers_Admin {
1078
  $data['css'] = ! empty( $meta['es_custom_css'] ) ? $meta['es_custom_css'] : get_post_meta( $data['tmpl_id'], 'es_custom_css', true );
1079
  $data['tasks'][] = 'css-inliner';
1080
  }
1081
-
1082
  // Add utm tracking task data to request if valid request.
1083
  if ( ES()->validate_service_request( array( 'utm_tracking' ) ) ) {
1084
 
1085
  if ( ! empty( $data['campaign_id'] ) ) {
1086
- $campaign_id = $data['campaign_id'];
1087
  $can_track_utm = ES()->mailer->can_track_utm( $data );
1088
  if ( $can_track_utm ) {
1089
- $meta = ES()->campaigns_db->get_campaign_meta_by_id( $campaign_id );
1090
- $data['html'] = $data['content'];
1091
- $data['utm_params']['utm_source'] = 'es';
1092
- $data['utm_params']['utm_medium'] = 'email';
1093
- $data['tasks'][] = 'utm-tracking';
1094
  // For broadcast campaign, utm campaign name is saved in campaign meta for other campaigns, it is saved in related template.
1095
  if ( ! empty( $meta['es_utm_campaign'] ) ) {
1096
  $data['utm_params']['utm_campaign'] = $meta['es_utm_campaign'];
1097
- } else if ( ! empty( $data['tmpl_id'] ) ) {
1098
  $data['utm_params']['utm_campaign'] = get_post_meta( $data['tmpl_id'], 'es_utm_campaign', true );
1099
  }
1100
  }
1101
  }
1102
-
1103
  }
1104
 
1105
  return $data;
1106
  }
1107
-
1108
  /**
1109
  * Method to check if utm tracking is enabled.
1110
  *
1111
  * @param array $data
1112
- *
1113
  * @return array $data
1114
- *
1115
  * @since 4.6.2
1116
  */
1117
  public function is_utm_tracking_enabled( $tracking_enabled = false, $data = array() ) {
@@ -1128,8 +1122,8 @@ class Email_Subscribers_Admin {
1128
  if ( ! empty( $campaign ) ) {
1129
  $campaign_type = $campaign['type'];
1130
  if ( 'newsletter' === $campaign_type ) {
1131
- $campaign_meta = maybe_unserialize( $campaign['meta'] );
1132
- $ig_es_track_utm = ! empty( $campaign_meta['enable_utm_tracking'] ) ? $campaign_meta['enable_utm_tracking']: $ig_es_track_utm;
1133
  }
1134
  }
1135
  }
@@ -1141,7 +1135,7 @@ class Email_Subscribers_Admin {
1141
 
1142
  return $tracking_enabled;
1143
  }
1144
-
1145
  /**
1146
  * Method to disable Icegram server cron.
1147
  *
@@ -1152,15 +1146,15 @@ class Email_Subscribers_Admin {
1152
  $handle_cron_data_service = new ES_Service_Handle_Cron_Data();
1153
  $handle_cron_data_service->delete_cron_data();
1154
  }
1155
-
1156
  /**
1157
  * Method to override service validation for some specific request
1158
  *
1159
- * @param bool $is_request_valid Is request valid.
1160
  * @param array $request_data Request data.
1161
- *
1162
  * @return bool $is_request_valid Is request valid.
1163
- *
1164
  * @since 4.6.2
1165
  */
1166
  public function maybe_override_service_validation( $is_request_valid, $request_data = array() ) {
@@ -1168,16 +1162,16 @@ class Email_Subscribers_Admin {
1168
  if ( empty( $request_data ) ) {
1169
  return $is_request_valid;
1170
  }
1171
-
1172
  $request_body = ! empty( $request_data['body'] ) ? $request_data['body'] : array();
1173
-
1174
  // Check if there are any request related tasks present.
1175
  if ( empty( $request_body ) || empty( $request_body['tasks'] ) ) {
1176
  return $is_request_valid;
1177
  }
1178
-
1179
  $request_tasks = $request_body['tasks'];
1180
-
1181
  // Check if request request is for storing es cron data.
1182
  if ( in_array( 'store-cron', $request_tasks, true ) ) {
1183
  // If request is for disable es cron.
@@ -1197,21 +1191,22 @@ class Email_Subscribers_Admin {
1197
  *
1198
  * @since 4.6.6
1199
  */
1200
- /*public function ig_es_send_additional_data_for_tracking() {
 
1201
 
1202
  // Send data only if user had opted for trial or user is on a premium plan.
1203
- $is_plan_valid = ES()->is_trial() || ES()->is_premium();
1204
 
1205
  // Check if the data is already sent once
1206
- $can_send_data = get_option( 'ig_es_send_additional_data_for_tracking', 'yes' );
1207
 
1208
  if ( $is_plan_valid && 'yes' === $can_send_data ) {
1209
-
1210
  update_option( 'ig_es_send_additional_data_for_tracking', 'no' );
1211
-
1212
- $url = 'https://api.icegram.com/';
1213
- $data = array(
1214
-
1215
  );
1216
 
1217
  $options = array(
@@ -1219,7 +1214,7 @@ class Email_Subscribers_Admin {
1219
  'method' => 'POST',
1220
  'body' => $data
1221
  );
1222
-
1223
  $response = wp_remote_post( $url, $options );
1224
  }
1225
 
@@ -1227,7 +1222,7 @@ class Email_Subscribers_Admin {
1227
 
1228
  /**
1229
  * Method to preview email through AJAX
1230
- *
1231
  * @since 4.6.11
1232
  */
1233
  public function preview_email_in_report() {
@@ -1238,23 +1233,24 @@ class Email_Subscribers_Admin {
1238
  $campaign_type = ig_es_get_request_data( 'campaign_type' );
1239
  $response = array();
1240
  $email_body = '';
1241
-
1242
  if ( ! empty( $report_id ) ) {
1243
 
1244
  if ( ! empty( $campaign_type ) && 'sequence_message' === $campaign_type ) {
1245
- $email_body = ES()->campaigns_db->get_campaign_by_id( $report_id );
1246
  } else {
1247
- $email_body = ES_DB_Mailing_Queue::get_mailing_queue_by_id( $report_id );
1248
  }
1249
- $es_email_type = get_option( 'ig_es_email_type' ); // Not the ideal way. Email type can differ while previewing sent email.
1250
  $response['template_html'] = ES_Common::es_process_template_body( $email_body['body'] );
1251
- /*if ( 'WP HTML MAIL' == $es_email_type || 'PHP HTML MAIL' == $es_email_type ) {
 
1252
  $response['template_html'] = ES_Common::es_process_template_body( $email_body['body'] );
1253
  } else {
1254
  $response['template_html'] = str_replace( '<br />', "\r\n", $email_body['body'] );
1255
  $response['template_html'] = str_replace( '<br>', "\r\n", $email_body['body'] );
1256
  }
1257
- */
1258
  }
1259
 
1260
  if ( ! empty( $response ) ) {
@@ -1264,7 +1260,7 @@ class Email_Subscribers_Admin {
1264
  }
1265
  ?>
1266
 
1267
- <?php
1268
  }
1269
 
1270
  /**
@@ -1297,7 +1293,7 @@ class Email_Subscribers_Admin {
1297
  if ( in_array( $screen_id, array( 'dashboard' ) ) ) {
1298
  wp_enqueue_style( 'ig_es_dashboard_style', plugin_dir_url( __FILE__ ) . 'css/es-wp-dashboard.css', array(), $this->version, 'all' );
1299
  }
1300
-
1301
  }
1302
 
1303
  /**
@@ -1307,14 +1303,14 @@ class Email_Subscribers_Admin {
1307
  */
1308
  public function dashboard_stats_widget() {
1309
 
1310
- $reports_data = ES_Reports_Data::get_dashboard_reports_data( 'es_wp_dashboard_widget', false, 30 );
1311
  $total_contacts_subscribed = isset( $reports_data['total_contacts_subscribed'] ) ? $reports_data['total_contacts_subscribed'] : 0;
1312
- $total_message_sent = isset( $reports_data['total_message_sent'] ) ? $reports_data['total_message_sent'] : 0;
1313
- $total_contact_lost = isset( $reports_data['total_contact_lost'] ) ? $reports_data['total_contact_lost'] : 0;
1314
- $avg_open_rate = isset( $reports_data['avg_open_rate'] ) ? $reports_data['avg_open_rate'] : 0;
1315
 
1316
- $campaign_report = isset( $reports_data['campaigns'][0] ) ? $reports_data['campaigns'][0] : '';
1317
- $reports_url = isset( $campaign_report['hash'] ) ? add_query_arg( 'list', $campaign_report['hash'], add_query_arg( 'action', 'view', admin_url( 'admin.php?page=es_reports' ) ) ) : '';
1318
 
1319
  $topics = ES_Common::get_useful_articles( false );
1320
 
@@ -1377,12 +1373,12 @@ class Email_Subscribers_Admin {
1377
  <div class="overflow-hidden">
1378
  <p class="px-4 text-base font-medium leading-6 text-gray-600">
1379
  <span class="rounded-md bg-gray-200 px-2 py-0.5">
1380
- <?php
1381
- echo esc_html__('Last Campaign', 'email-subscribers');
1382
  ?>
1383
  </span>
1384
  </p>
1385
- <?php
1386
  if ( ! empty( $campaign_report ) ) {
1387
  ?>
1388
  <a href="<?php echo esc_url( $reports_url ); ?>" class="block px-2 hover:bg-gray-50 focus:outline-none focus:bg-gray-50 transition duration-150 ease-in-out" target="_blank">
@@ -1395,9 +1391,9 @@ class Email_Subscribers_Admin {
1395
  </svg>
1396
  <?php
1397
  echo esc_html( $campaign_report['type'] );
1398
-
1399
  $allowed_html_tags = ig_es_allowed_html_tags_in_esc();
1400
- $status = ES_Common::get_campaign_status_icon( $campaign_report['status'] );
1401
  echo wp_kses( $status, $allowed_html_tags );
1402
  ?>
1403
 
@@ -1421,7 +1417,7 @@ class Email_Subscribers_Admin {
1421
  <span class="leading-none font-medium text-base text-indigo-500">
1422
  <?php echo esc_html( $campaign_report['total_opens'] ); ?> (
1423
  <?php
1424
- echo esc_html( $campaign_report['campaign_opens_rate'] );
1425
  ?>
1426
  %)
1427
  </span>
@@ -1438,9 +1434,9 @@ class Email_Subscribers_Admin {
1438
  </div>
1439
  </div>
1440
  </a>
1441
- <?php
1442
  } else {
1443
- echo '<p class="pl-4 font-medium text-gray-500">' . esc_html__('No campaigns sent yet', 'email-subscribers') . '<p>';
1444
  }
1445
  ?>
1446
  </div>
@@ -1448,7 +1444,7 @@ class Email_Subscribers_Admin {
1448
  <p class="px-4 text-base font-medium leading-6 text-gray-600">
1449
  <span class="rounded-md bg-gray-200 px-2 py-0.5">
1450
  <?php
1451
- echo esc_html__('Latest Blog Posts from Icegram', 'email-subscribers');
1452
  ?>
1453
  </span>
1454
  </p>
@@ -1459,9 +1455,9 @@ class Email_Subscribers_Admin {
1459
  <a href="<?php echo esc_url( $topics[ $index ]['link'] ); ?>" class="hover:underline font-medium block pr-3 transition duration-150 ease-in-out focus:outline-none focus:bg-gray-50" target="_blank">
1460
  <div class="flex items-center px-2 py-1 md:justify-between">
1461
  <div class="text-sm leading-5 text-gray-700">
1462
- <?php
1463
  echo wp_kses_post( $topics[ $index ]['title'] );
1464
- if ( ! empty( $topics[ $index ]['label'] ) ) {
1465
  ?>
1466
  <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?php echo esc_attr( $topics[ $index ]['label_class'] ); ?>"><?php echo esc_html( $topics[ $index ]['label'] ); ?></span>
1467
  <?php } ?>
50
  * @param string $version The version of this plugin.
51
  *
52
  * @since 4.0
 
53
  */
54
  public function __construct( $email_subscribers, $version ) {
55
 
59
  // Reorder ES Submenu
60
 
61
  // Commenting out since we are now registering the submenus in the order required. Therefore no need to change the submenu order later on.
62
+ // add_filter( 'custom_menu_order', array( $this, 'submenu_order' ) );
63
 
64
  add_action( 'admin_menu', array( $this, 'email_subscribers_admin_menu' ) );
65
  add_action( 'wp_ajax_es_klawoo_subscribe', array( $this, 'klawoo_subscribe' ) );
70
  add_action( 'wp_ajax_ig_es_toggle_campaign_status', array( $this, 'toggle_campaign_status' ) );
71
 
72
  add_action( 'admin_init', array( $this, 'ob_start' ) );
73
+
74
  add_action( 'init', array( $this, 'save_screen_option' ) );
75
+
76
  // Add spam score ajax action.
77
  add_action( 'wp_ajax_es_get_spam_score', array( &$this, 'get_spam_score' ) );
78
+
79
  // Add send cron data action.
80
  add_action( 'admin_head', array( $this, 'send_cron_data' ) );
81
  add_action( 'ig_es_after_settings_save', array( $this, 'send_cron_data' ) );
82
+
 
83
  // Process and add premium service data(Inline CSS, UTM Tracking etc) to template body.
84
+ add_filter( 'es_after_process_template_body', array( $this, 'add_premium_services_data' ) );
85
+
86
  // Filter to add premium service request data.
87
+ add_filter( 'ig_es_util_data', array( $this, 'add_util_data' ) );
88
+
89
  // Filter to check if utm tracking is enabled.
90
+ add_filter( 'ig_es_track_utm', array( $this, 'is_utm_tracking_enabled' ), 10, 2 );
91
+
92
  // Disable Icegram server cron when plugin is deactivated.
93
  add_action( 'ig_es_plugin_deactivate', array( $this, 'disable_server_cron' ) );
94
+
95
+ // add_action( 'admin_init', array( $this, 'ig_es_send_additional_data_for_tracking' ) );
96
+
97
  // Filter to hook custom validation for specific service request.
98
  add_filter( 'ig_es_service_request_custom_validation', array( $this, 'maybe_override_service_validation' ), 10, 2 );
99
 
100
  // Ajax handler for email preview
101
  add_action( 'wp_ajax_ig_es_preview_email_report', array( $this, 'preview_email_in_report' ) );
102
+ add_action( 'wp_ajax_ajax_fetch_report_list', array( $this, 'ajax_fetch_report_list_callback' ) );
103
 
104
  if ( class_exists( 'IG_ES_Premium_Services_UI' ) ) {
105
  IG_ES_Premium_Services_UI::instance();
169
  'broadcast_subject_empty_message' => __( 'Please add a broadcast subject before saving.', 'email-subscribers' ),
170
  'empty_template_message' => __( 'Please add email body.', 'email-subscribers' ),
171
  'remove_conditions_message' => __( 'Do you really like to remove all conditions?', 'email-subscribers' ),
172
+
173
  // Workflows messages.
174
+ 'no_trigger_message' => __( 'Please select a trigger before saving the workflow.', 'email-subscribers' ),
175
+ 'no_actions_message' => __( 'Please add some actions before saving the workflow.', 'email-subscribers' ),
176
+ 'no_action_selected_message' => __( 'Please select an action that this workflow should perform before saving the workflow.', 'email-subscribers' ),
177
+ 'trigger_change_message' => __( 'Changing the trigger will remove existing actions. Do you want to proceed anyway?.', 'email-subscribers' ),
178
+ 'placeholder_copied_message' => __( 'Copied!', 'email-subscribers' ),
179
+ 'delete_confirmation_message' => __( 'Are you sure?', 'email-subscribers' ),
180
 
181
  // Import subscribers messages.
182
+ 'select_status' => esc_html__( 'Please select the status for the importing contacts!', 'email-subscribers' ),
183
+ 'select_list' => esc_html__( 'Please select a list for importing contacts!', 'email-subscribers' ),
184
+ 'select_email_column' => esc_html__( 'Please select the email address column!', 'email-subscribers' ),
185
+ 'prepare_data' => esc_html__( 'Preparing Data', 'email-subscribers' ),
186
  /* translators: %s: Upload progress */
187
+ 'uploading' => esc_html__( 'Uploading...%s', 'email-subscribers' ),
188
  /* translators: %s: Import progress */
189
+ 'import_contacts' => esc_html__( 'Importing contacts...%s', 'email-subscribers' ),
190
  /* translators: %s: Import failed svg icon */
191
+ 'import_failed' => esc_html__( 'Import failed! %s', 'email-subscribers' ),
192
+ 'no_windowclose' => esc_html__( 'Please do not close this window until it completes...', 'email-subscribers' ),
193
+ 'prepare_import' => esc_html__( 'Preparing Import...', 'email-subscribers' ),
194
  /* translators: 1. Imported contacts count 2. Total contacts count 3. Failed to import count 4. Memory usage */
195
+ 'current_stats' => esc_html__( 'Currently %1$s of %2$s imported with %3$s errors. %4$s %5$s memory usage', 'email-subscribers' ),
196
  /* translators: 1 Duplicate found email message */
197
+ 'duplicate_emails_found_message' => __( '%1$s duplicate emails found.', 'email-subscribers' ),
198
  /* translators: %s: Time left in minutes */
199
+ 'estimate_time' => esc_html__( 'Estimate time left: %s minutes', 'email-subscribers' ),
200
  /* translators: %s: Next attempt delaly time */
201
+ 'continues_in' => esc_html__( 'Continues in %s seconds', 'email-subscribers' ),
202
+ 'error_importing' => esc_html__( 'There was a problem during importing contacts. Please check the error logs for more information!', 'email-subscribers' ),
203
+ 'confirm_import' => esc_html__( 'Do you really like to import these contacts?', 'email-subscribers' ),
204
  /* translators: %s: Process complete svg icon */
205
+ 'import_complete' => esc_html__( 'Import complete! %s', 'email-subscribers' ),
206
+ 'onbeforeunloadimport' => esc_html__( 'You are currently importing subscribers! If you leave the page all pending subscribers don\'t get imported!', 'email-subscribers' ),
207
+ 'api_verification_success' => esc_html__( 'API is valid. Fetching lists...', 'email-subscribers' ),
208
  'mailchimp_notice_nowindow_close' => esc_html__( 'Fetching contacts from MailChimp...Please do not close this window', 'email-subscribers' ),
209
  ),
210
+ 'is_pro' => ES()->is_pro(),
211
  );
212
 
213
  wp_localize_script( $this->email_subscribers, 'ig_es_js_data', $ig_es_js_data );
226
  */
227
  require_once ES_PLUGIN_DIR . 'lite/includes/libraries/wp-js-editor/wp-js-editor.php';
228
  }
229
+
230
  // Load required html/js for dynamic WordPress editor.
231
  ig_es_wp_js_editor_admin_scripts();
232
 
233
  // Localize additional required data for workflow functionality
234
  $workflows_data = ES_Workflow_Admin_Edit::get_workflow_data();
235
  wp_localize_script( $this->email_subscribers, 'ig_es_workflows_data', $workflows_data );
236
+ } elseif ( 'es_subscribers' === $get_page ) {
237
 
238
  $action = ig_es_get_request_data( 'action' );
239
  if ( 'import' === $action ) {
242
  }
243
  }
244
 
245
+ // timepicker
246
  wp_register_script( $this->email_subscribers . '-timepicker', plugin_dir_url( __FILE__ ) . 'js/jquery.timepicker.js', array( 'jquery' ), ES_PLUGIN_VERSION, true );
247
  wp_enqueue_script( $this->email_subscribers . '-timepicker' );
248
 
 
249
  if ( ! empty( $get_page ) && 'es_dashboard' === $get_page || 'es_reports' === $get_page ) {
250
  wp_enqueue_script( 'frappe-js', 'https://unpkg.com/frappe-charts@1.5.2/dist/frappe-charts.min.iife.js', array( 'jquery' ), $this->version, false );
251
  }
 
252
 
253
  }
254
 
255
  public function remove_submenu() {
256
+ // remove submenues
257
  ?>
258
  <script type="text/javascript">
259
  jQuery(document).ready(function () {
265
  </script>
266
  <?php
267
  }
268
+
269
  public function email_subscribers_admin_menu() {
270
+
271
  $accessible_sub_menus = ES_Common::ig_es_get_accessible_sub_menus();
272
+
273
  if ( count( $accessible_sub_menus ) > 0 ) {
274
 
275
  $menu_title = ES()->get_admin_menu_title();
276
 
277
  // This adds the main menu page.
278
  add_menu_page( $menu_title, $menu_title, 'edit_posts', 'es_dashboard', array( $this, 'es_dashboard_callback' ), 'dashicons-email', 30 );
279
+
280
  if ( 'woo' === IG_ES_PLUGIN_PLAN ) {
281
  // Add Icegram submenu under WooCommerce marketing admin menu.
282
  add_submenu_page( 'woocommerce-marketing', $menu_title, $menu_title, 'manage_woocommerce', 'es_dashboard', array( $this, 'es_dashboard_callback' ) );
283
  }
284
+
285
  // Submenu.
286
  add_submenu_page( 'es_dashboard', __( 'Dashboard', 'email-subscribers' ), __( 'Dashboard', 'email-subscribers' ), 'edit_posts', 'es_dashboard', array( $this, 'es_dashboard_callback' ) );
287
  }
288
+
289
  if ( in_array( 'audience', $accessible_sub_menus ) ) {
290
  // Add Contacts Submenu
291
  $hook = add_submenu_page( 'es_dashboard', __( 'Audience', 'email-subscribers' ), __( 'Audience', 'email-subscribers' ), 'edit_posts', 'es_subscribers', array( $this, 'render_contacts' ) );
292
  add_action( "load-$hook", array( 'ES_Contacts_Table', 'screen_options' ) );
293
+
294
  // Add Lists Submenu
295
  $hook = add_submenu_page( 'es_dashboard', __( 'Lists', 'email-subscribers' ), '<span id="ig-es-lists">' . __( 'Lists', 'email-subscribers' ) . '</span>', 'edit_posts', 'es_lists', array( $this, 'render_lists' ) );
296
+ // add_action( "load-$hook", array( 'ES_Lists_Table', 'screen_options' ) );
297
  }
298
 
299
  if ( in_array( 'forms', $accessible_sub_menus ) ) {
300
  // Add Forms Submenu
301
  $hook = add_submenu_page( 'es_dashboard', __( 'Forms', 'email-subscribers' ), __( 'Forms', 'email-subscribers' ), 'edit_posts', 'es_forms', array( $this, 'render_forms' ) );
302
+ // add_action( "load-$hook", array( 'ES_Forms_Table', 'screen_options' ) );
303
  }
304
+
305
  if ( in_array( 'campaigns', $accessible_sub_menus ) ) {
306
  // Add Campaigns Submenu
307
  $hook = add_submenu_page( 'es_dashboard', __( 'Campaigns', 'email-subscribers' ), __( 'Campaigns', 'email-subscribers' ), 'edit_posts', 'es_campaigns', array( $this, 'render_campaigns' ) );
308
+ // add_action( "load-$hook", array( 'ES_Campaigns_Table', 'screen_options' ) );
309
+
310
  // Start-IG-Code.
311
  add_submenu_page( 'es_dashboard', __( 'Post Notifications', 'email-subscribers' ), '<span id="ig-es-post-notifications">' . __( 'Post Notifications', 'email-subscribers' ) . '</span>', 'edit_posts', 'es_notifications', array( $this, 'load_post_notifications' ) );
312
  // End-IG-Code.
313
  add_submenu_page( 'es_dashboard', __( 'Broadcast', 'email-subscribers' ), '<span id="ig-es-broadcast">' . __( 'Broadcast', 'email-subscribers' ) . '</span>', 'edit_posts', 'es_newsletters', array( $this, 'load_newsletters' ) );
314
  add_submenu_page( null, __( 'Template Preview', 'email-subscribers' ), __( 'Template Preview', 'email-subscribers' ), 'edit_posts', 'es_template_preview', array( $this, 'load_preview' ) );
315
+
316
  }
317
+
318
  if ( in_array( 'workflows', $accessible_sub_menus ) ) {
319
 
320
  // Add Workflows Submenu
321
  $hook = add_submenu_page( 'es_dashboard', __( 'Workflows', 'email-subscribers' ), __( 'Workflows', 'email-subscribers' ), 'edit_posts', 'es_workflows', array( $this, 'render_workflows' ) );
322
 
323
+ // add_action( "load-$hook", array( 'ES_Workflows_Table', 'screen_options' ) );
324
  add_action( "load-$hook", array( 'ES_Workflow_Admin_Edit', 'register_meta_boxes' ) );
325
  add_action( "admin_footer-$hook", array( 'ES_Workflow_Admin_Edit', 'print_script_in_footer' ) );
326
  add_action( 'admin_init', array( 'ES_Workflow_Admin_Edit', 'maybe_save' ) );
363
  new ES_Tracking();
364
  }
365
 
366
+ /**
367
  * Function for Klawoo's Subscribe form on Help & Info page
368
+ *
369
  * @param boolean $return Flag to check return response instead of exiting in the function itself.
370
+ */
371
  public static function klawoo_subscribe( $return = false ) {
372
 
373
  // We don't need to do nonce validation in case if the function is being called from other function.
400
 
401
  $options = array(
402
  'timeout' => 15,
403
+ 'method' => $method,
404
  );
405
 
406
  if ( 'POST' == $method ) {
583
 
584
  ksort( $reorder_es_menu );
585
 
586
+ // $submenu['es_dashboard'] = $reorder_es_menu;
587
  }
588
 
589
+ // Return the new submenu order
590
  return $menu_order;
591
  }
592
 
607
 
608
  }
609
 
610
+ // save skip signup option
611
  public function es_save_onboarding_skip() {
612
 
613
  $es_skip = ig_es_get_request_data( 'es_skip' );
614
  $option_name = ig_es_get_request_data( 'option_name' );
615
 
 
616
  if ( '1' == $es_skip && ! empty( $option_name ) ) {
617
  /**
618
  * If user logged in then only save option.
636
  $conditions = ig_es_get_request_data( 'conditions', array() );
637
  $get_count = ig_es_get_request_data( 'get_count', 'no' );
638
 
639
+ if ( 0 == $list_id && empty( $conditions ) ) {
640
  return 0;
641
  }
642
 
643
  $response_data = array();
644
+
645
  if ( ! empty( $conditions ) ) {
646
  if ( 'yes' === $get_count ) {
647
+ $args = array(
648
  'lists' => $list_id,
649
  'conditions' => $conditions,
650
  'status' => $status,
651
  'return_count' => true,
652
  );
653
+ $query = new IG_ES_Subscribers_Query();
654
  $response_data['total'] = $query->run( $args );
655
  }
656
  ob_start();
657
  do_action( 'ig_es_campaign_show_conditions', $conditions );
658
  $response_data['conditions_html'] = ob_get_clean();
659
  } else {
660
+ $response_data['total'] = ES()->lists_contacts_db->get_total_count_by_list( $list_id, $status );
661
  }
662
 
663
  if ( ! empty( $response_data['total'] ) ) {
664
  $response_data['total'] = number_format( $response_data['total'] );
665
  }
666
+
667
  die( json_encode( $response_data ) );
668
  }
669
 
677
  $post_temp_arr = get_post( $template_id );
678
  $result['subject'] = ! empty( $post_temp_arr->post_title ) ? $post_temp_arr->post_title : '';
679
  $result['body'] = ! empty( $post_temp_arr->post_content ) ? $post_temp_arr->post_content : '';
680
+ // get meta data of template
681
  // $active_plugins = $ig_es_tracker::get_active_plugins();
682
  if ( ES()->is_starter() ) {
683
  $result['inline_css'] = get_post_meta( $template_id, 'es_custom_css', true );
691
  * Get Email Subscribers' screen options
692
  *
693
  * @return array
694
+ *
695
  * @since 4.5.4
696
  */
697
  public function get_admin_screen_options() {
894
 
895
  /**
896
  * Method to start output buffering to allows admin screens to make redirects later on.
897
+ *
898
  * @since 4.5.2
899
  */
900
  public function ob_start() {
903
 
904
  /**
905
  * Method to get spam score
906
+ *
907
  * @since 4.6.1
908
  */
909
  public function get_spam_score() {
910
 
911
  check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' );
912
+
913
  global $post;
914
 
915
  $response = array(
917
  'error_message' => __( 'Something went wrong', 'email-subscribers' ),
918
  );
919
 
920
+ $admin_email = get_option( 'admin_email' );
921
  if ( ! empty( $_REQUEST['action'] ) && 'es_get_spam_score' == $_REQUEST['action'] ) {
922
 
923
  $sender_data = array();
946
  $header .= 'Subject:' . $subject . "\n";
947
  }
948
 
949
+ $header .= 'Date: ' . gmdate( 'r' ) . "\n";
950
+ $header .= 'To: ' . $admin_email . "\n";
951
+ $header .= 'Message-ID: <' . $admin_email . ">\n";
952
+ $header .= "MIME-Version: 1.0\n";
953
+ $data['email'] = $header . $content;
954
+ $data['tasks'][] = 'spam-score';
955
 
956
  $spam_score_service = new ES_Service_Spam_Score_Check();
957
  $service_response = $spam_score_service->get_spam_score( $data );
985
  $from_email = $sender_data['from_email'];
986
  }
987
 
988
+ // adding missing from name
989
  if ( empty( $from_name ) ) {
990
  $from_name = get_option( 'ig_es_from_name', true );
991
  }
992
 
993
+ // adding missing from email
994
  if ( empty( $from_email ) ) {
995
  $from_email = get_option( 'ig_es_from_email', true );
996
  }
1001
  $headers = array(
1002
  "From: \"$sender_name\" <$sender_email>",
1003
  'Return-Path: <' . $sender_email . '>',
1004
+ 'Reply-To: "' . $sender_name . '" <' . $sender_email . '>',
1005
  );
1006
 
1007
  if ( in_array( $get_email_type, array( 'php_html_mail', 'php_plaintext_mail' ) ) ) {
1026
  */
1027
  public function send_cron_data( $options = array() ) {
1028
 
1029
+ if ( ! ES()->is_es_admin_screen() ) {
1030
  return;
1031
  }
1032
+
1033
  $handle_cron_data_service = new ES_Service_Handle_Cron_Data();
1034
+
1035
  // Send cron data to server
1036
  $handle_cron_data_service->handle_es_cron_data( $options );
1037
  }
1038
+
1039
  /**
1040
  * Method to add ES service data(Inline CSS, UTM tracking to links etc) to email content
1041
  *
1042
  * @param array $data
1043
+ *
1044
  * @return array $data
1045
+ *
1046
  * @since 4.6.2
1047
  */
1048
  public function add_premium_services_data( $data = array() ) {
1049
 
1050
  $process_email_content_service = new ES_Service_Process_Email_Content();
1051
+
1052
  $data = $process_email_content_service->process_email_content( $data );
1053
+
1054
  return $data;
1055
  }
1056
+
1057
  /**
1058
  * Method to add ES service data(Inline CSS, UTM tracking to links etc) to email content
1059
  *
1060
  * @param array $data
1061
+ *
1062
  * @return array $data
1063
+ *
1064
  * @since 4.6.2
1065
  */
1066
  public function add_util_data( $data = array() ) {
1073
  $data['css'] = ! empty( $meta['es_custom_css'] ) ? $meta['es_custom_css'] : get_post_meta( $data['tmpl_id'], 'es_custom_css', true );
1074
  $data['tasks'][] = 'css-inliner';
1075
  }
1076
+
1077
  // Add utm tracking task data to request if valid request.
1078
  if ( ES()->validate_service_request( array( 'utm_tracking' ) ) ) {
1079
 
1080
  if ( ! empty( $data['campaign_id'] ) ) {
1081
+ $campaign_id = $data['campaign_id'];
1082
  $can_track_utm = ES()->mailer->can_track_utm( $data );
1083
  if ( $can_track_utm ) {
1084
+ $meta = ES()->campaigns_db->get_campaign_meta_by_id( $campaign_id );
1085
+ $data['html'] = $data['content'];
1086
+ $data['utm_params']['utm_source'] = 'es';
1087
+ $data['utm_params']['utm_medium'] = 'email';
1088
+ $data['tasks'][] = 'utm-tracking';
1089
  // For broadcast campaign, utm campaign name is saved in campaign meta for other campaigns, it is saved in related template.
1090
  if ( ! empty( $meta['es_utm_campaign'] ) ) {
1091
  $data['utm_params']['utm_campaign'] = $meta['es_utm_campaign'];
1092
+ } elseif ( ! empty( $data['tmpl_id'] ) ) {
1093
  $data['utm_params']['utm_campaign'] = get_post_meta( $data['tmpl_id'], 'es_utm_campaign', true );
1094
  }
1095
  }
1096
  }
 
1097
  }
1098
 
1099
  return $data;
1100
  }
1101
+
1102
  /**
1103
  * Method to check if utm tracking is enabled.
1104
  *
1105
  * @param array $data
1106
+ *
1107
  * @return array $data
1108
+ *
1109
  * @since 4.6.2
1110
  */
1111
  public function is_utm_tracking_enabled( $tracking_enabled = false, $data = array() ) {
1122
  if ( ! empty( $campaign ) ) {
1123
  $campaign_type = $campaign['type'];
1124
  if ( 'newsletter' === $campaign_type ) {
1125
+ $campaign_meta = maybe_unserialize( $campaign['meta'] );
1126
+ $ig_es_track_utm = ! empty( $campaign_meta['enable_utm_tracking'] ) ? $campaign_meta['enable_utm_tracking'] : $ig_es_track_utm;
1127
  }
1128
  }
1129
  }
1135
 
1136
  return $tracking_enabled;
1137
  }
1138
+
1139
  /**
1140
  * Method to disable Icegram server cron.
1141
  *
1146
  $handle_cron_data_service = new ES_Service_Handle_Cron_Data();
1147
  $handle_cron_data_service->delete_cron_data();
1148
  }
1149
+
1150
  /**
1151
  * Method to override service validation for some specific request
1152
  *
1153
+ * @param bool $is_request_valid Is request valid.
1154
  * @param array $request_data Request data.
1155
+ *
1156
  * @return bool $is_request_valid Is request valid.
1157
+ *
1158
  * @since 4.6.2
1159
  */
1160
  public function maybe_override_service_validation( $is_request_valid, $request_data = array() ) {
1162
  if ( empty( $request_data ) ) {
1163
  return $is_request_valid;
1164
  }
1165
+
1166
  $request_body = ! empty( $request_data['body'] ) ? $request_data['body'] : array();
1167
+
1168
  // Check if there are any request related tasks present.
1169
  if ( empty( $request_body ) || empty( $request_body['tasks'] ) ) {
1170
  return $is_request_valid;
1171
  }
1172
+
1173
  $request_tasks = $request_body['tasks'];
1174
+
1175
  // Check if request request is for storing es cron data.
1176
  if ( in_array( 'store-cron', $request_tasks, true ) ) {
1177
  // If request is for disable es cron.
1191
  *
1192
  * @since 4.6.6
1193
  */
1194
+ /*
1195
+ public function ig_es_send_additional_data_for_tracking() {
1196
 
1197
  // Send data only if user had opted for trial or user is on a premium plan.
1198
+ $is_plan_valid = ES()->is_trial() || ES()->is_premium();
1199
 
1200
  // Check if the data is already sent once
1201
+ $can_send_data = get_option( 'ig_es_send_additional_data_for_tracking', 'yes' );
1202
 
1203
  if ( $is_plan_valid && 'yes' === $can_send_data ) {
1204
+
1205
  update_option( 'ig_es_send_additional_data_for_tracking', 'no' );
1206
+
1207
+ $url = 'https://api.icegram.com/';
1208
+ $data = array(
1209
+
1210
  );
1211
 
1212
  $options = array(
1214
  'method' => 'POST',
1215
  'body' => $data
1216
  );
1217
+
1218
  $response = wp_remote_post( $url, $options );
1219
  }
1220
 
1222
 
1223
  /**
1224
  * Method to preview email through AJAX
1225
+ *
1226
  * @since 4.6.11
1227
  */
1228
  public function preview_email_in_report() {
1233
  $campaign_type = ig_es_get_request_data( 'campaign_type' );
1234
  $response = array();
1235
  $email_body = '';
1236
+
1237
  if ( ! empty( $report_id ) ) {
1238
 
1239
  if ( ! empty( $campaign_type ) && 'sequence_message' === $campaign_type ) {
1240
+ $email_body = ES()->campaigns_db->get_campaign_by_id( $report_id );
1241
  } else {
1242
+ $email_body = ES_DB_Mailing_Queue::get_mailing_queue_by_id( $report_id );
1243
  }
1244
+ $es_email_type = get_option( 'ig_es_email_type' ); // Not the ideal way. Email type can differ while previewing sent email.
1245
  $response['template_html'] = ES_Common::es_process_template_body( $email_body['body'] );
1246
+ /*
1247
+ if ( 'WP HTML MAIL' == $es_email_type || 'PHP HTML MAIL' == $es_email_type ) {
1248
  $response['template_html'] = ES_Common::es_process_template_body( $email_body['body'] );
1249
  } else {
1250
  $response['template_html'] = str_replace( '<br />', "\r\n", $email_body['body'] );
1251
  $response['template_html'] = str_replace( '<br>', "\r\n", $email_body['body'] );
1252
  }
1253
+ */
1254
  }
1255
 
1256
  if ( ! empty( $response ) ) {
1260
  }
1261
  ?>
1262
 
1263
+ <?php
1264
  }
1265
 
1266
  /**
1293
  if ( in_array( $screen_id, array( 'dashboard' ) ) ) {
1294
  wp_enqueue_style( 'ig_es_dashboard_style', plugin_dir_url( __FILE__ ) . 'css/es-wp-dashboard.css', array(), $this->version, 'all' );
1295
  }
1296
+
1297
  }
1298
 
1299
  /**
1303
  */
1304
  public function dashboard_stats_widget() {
1305
 
1306
+ $reports_data = ES_Reports_Data::get_dashboard_reports_data( 'es_wp_dashboard_widget', false, 30 );
1307
  $total_contacts_subscribed = isset( $reports_data['total_contacts_subscribed'] ) ? $reports_data['total_contacts_subscribed'] : 0;
1308
+ $total_message_sent = isset( $reports_data['total_message_sent'] ) ? $reports_data['total_message_sent'] : 0;
1309
+ $total_contact_lost = isset( $reports_data['total_contact_lost'] ) ? $reports_data['total_contact_lost'] : 0;
1310
+ $avg_open_rate = isset( $reports_data['avg_open_rate'] ) ? $reports_data['avg_open_rate'] : 0;
1311
 
1312
+ $campaign_report = isset( $reports_data['campaigns'][0] ) ? $reports_data['campaigns'][0] : '';
1313
+ $reports_url = isset( $campaign_report['hash'] ) ? add_query_arg( 'list', $campaign_report['hash'], add_query_arg( 'action', 'view', admin_url( 'admin.php?page=es_reports' ) ) ) : '';
1314
 
1315
  $topics = ES_Common::get_useful_articles( false );
1316
 
1373
  <div class="overflow-hidden">
1374
  <p class="px-4 text-base font-medium leading-6 text-gray-600">
1375
  <span class="rounded-md bg-gray-200 px-2 py-0.5">
1376
+ <?php
1377
+ echo esc_html__( 'Last Campaign', 'email-subscribers' );
1378
  ?>
1379
  </span>
1380
  </p>
1381
+ <?php
1382
  if ( ! empty( $campaign_report ) ) {
1383
  ?>
1384
  <a href="<?php echo esc_url( $reports_url ); ?>" class="block px-2 hover:bg-gray-50 focus:outline-none focus:bg-gray-50 transition duration-150 ease-in-out" target="_blank">
1391
  </svg>
1392
  <?php
1393
  echo esc_html( $campaign_report['type'] );
1394
+
1395
  $allowed_html_tags = ig_es_allowed_html_tags_in_esc();
1396
+ $status = ES_Common::get_campaign_status_icon( $campaign_report['status'] );
1397
  echo wp_kses( $status, $allowed_html_tags );
1398
  ?>
1399
 
1417
  <span class="leading-none font-medium text-base text-indigo-500">
1418
  <?php echo esc_html( $campaign_report['total_opens'] ); ?> (
1419
  <?php
1420
+ echo esc_html( $campaign_report['campaign_opens_rate'] );
1421
  ?>
1422
  %)
1423
  </span>
1434
  </div>
1435
  </div>
1436
  </a>
1437
+ <?php
1438
  } else {
1439
+ echo '<p class="pl-4 font-medium text-gray-500">' . esc_html__( 'No campaigns sent yet', 'email-subscribers' ) . '<p>';
1440
  }
1441
  ?>
1442
  </div>
1444
  <p class="px-4 text-base font-medium leading-6 text-gray-600">
1445
  <span class="rounded-md bg-gray-200 px-2 py-0.5">
1446
  <?php
1447
+ echo esc_html__( 'Latest Blog Posts from Icegram', 'email-subscribers' );
1448
  ?>
1449
  </span>
1450
  </p>
1455
  <a href="<?php echo esc_url( $topics[ $index ]['link'] ); ?>" class="hover:underline font-medium block pr-3 transition duration-150 ease-in-out focus:outline-none focus:bg-gray-50" target="_blank">
1456
  <div class="flex items-center px-2 py-1 md:justify-between">
1457
  <div class="text-sm leading-5 text-gray-700">
1458
+ <?php
1459
  echo wp_kses_post( $topics[ $index ]['title'] );
1460
+ if ( ! empty( $topics[ $index ]['label'] ) ) {
1461
  ?>
1462
  <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?php echo esc_attr( $topics[ $index ]['label_class'] ); ?>"><?php echo esc_html( $topics[ $index ]['label'] ); ?></span>
1463
  <?php } ?>
lite/admin/class-ig-es-campaign-rules.php CHANGED
@@ -16,13 +16,11 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
16
 
17
  /**
18
  * Campaign rules
19
- *
20
  */
21
  private $campaign_rules = array();
22
-
23
  /**
24
  * Subscriber related fields
25
- *
26
  */
27
  private $fields = array();
28
 
@@ -30,27 +28,27 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
30
  * Campaign related fields
31
  */
32
  private $campaign_related = array();
33
-
34
  /**
35
  * Aggregate campaigns fields
36
  */
37
  private $aggregate_campaigns = array();
38
-
39
  /**
40
  * Rule operators
41
  */
42
  private $operators = array();
43
-
44
  /**
45
  * Simple operators
46
  */
47
  private $simple_operators = array();
48
-
49
  /**
50
  * String operators
51
  */
52
  private $string_operators = array();
53
-
54
  /**
55
  * Boolean operators
56
  */
@@ -62,10 +60,10 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
62
  public function __construct() {
63
  add_action( 'init', array( $this, 'init' ) );
64
  }
65
-
66
  /**
67
  * Initialize campaign rules
68
- *
69
  * @since 4.6.12
70
  */
71
  public function init() {
@@ -77,7 +75,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
77
  $this->string_operators = $this->get_string_operators();
78
  $this->bool_operators = $this->get_bool_operators();
79
  $this->campaign_rules = self::get_campaign_rules();
80
-
81
  add_action( 'ig_es_show_campaign_rules', array( $this, 'show_campaign_rules' ), 10, 2 );
82
  add_action( 'ig_es_campaign_show_conditions', array( $this, 'show_conditions' ) );
83
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
@@ -104,7 +102,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
104
  * @since 4.6.11
105
  */
106
  public function show_campaign_rules( $campaign_id = 0, $campaign_data = array() ) {
107
-
108
  $current_page = ig_es_get_request_data( 'page' );
109
 
110
  $campaign_type = '';
@@ -113,28 +111,28 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
113
  } else {
114
  $campaign_type = 'sequence_message';
115
  }
116
-
117
  $conditions = array();
118
  if ( ! empty( $campaign_data['meta'] ) ) {
119
  $campaign_meta = maybe_unserialize( $campaign_data['meta'] );
120
- $conditions = ! empty( $campaign_meta['list_conditions'] ) ? $campaign_meta['list_conditions'] : array();
121
  }
122
 
123
  $args = array();
124
  if ( 'newsletter' === $campaign_type ) {
125
  $args = array(
126
  'include_types' => array(
127
- 'newsletter'
128
  ),
129
- 'status' => array(
130
  IG_ES_CAMPAIGN_STATUS_QUEUED,
131
- IG_ES_CAMPAIGN_STATUS_FINISHED
132
  ),
133
  );
134
  } else {
135
  $args = array(
136
  'include_types' => array(
137
- 'sequence_message'
138
  ),
139
  );
140
  }
@@ -143,19 +141,19 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
143
  $args['campaigns_not_in'] = array( $campaign_id );
144
  }
145
  $all_campaigns = ES()->campaigns_db->get_all_campaigns( $args );
146
-
147
  $lists = ES()->lists_db->get_list_id_name_map();
148
  if ( ! empty( $all_campaigns ) ) {
149
  $all_campaigns_stati = array_column( $all_campaigns, 'status' );
150
  }
151
 
152
  $countries_data = ES_Geolocation::get_countries();
153
-
154
  $input_name = 'es_newsletters' === $current_page ? 'broadcast_data[meta][list_conditions]' : 'seq_data[' . $campaign_id . '][list_conditions]';
155
 
156
- $select_list_attr = ES()->is_pro() ? 'multiple="multiple"' : '';
157
- $select_list_name = ES()->is_pro() ? 'broadcast_data[list_ids][]' : 'broadcast_data[list_ids]';
158
- $select_list_class = ES()->is_pro() ? 'ig-es-campaign-rule-form-multiselect' : 'form-select';
159
 
160
  $sidebar_id = 'sidebar_' . $campaign_id;
161
  ?>
@@ -229,8 +227,8 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
229
  <div class="ig-es-conditions px-6 h-full">
230
  <div class="ig-es-condition-container"></div>
231
  <div class="ig-es-conditions-wrap mt-1 mb-3 overflow-auto">
232
- <?php
233
-
234
  array_unshift(
235
  $conditions,
236
  array(
@@ -242,8 +240,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
242
  )
243
  );
244
 
245
-
246
- foreach ( $conditions as $i => $condition_group ) :
247
  ?>
248
  <div class="ig-es-condition-group bg-white border border-gray-200 rounded-md my-2 pb-12 relative block px-4 rounded-lg pt-2 mt-2 mb-12" data-id="<?php echo esc_attr( $i ); ?>" data-operator="<?php esc_attr_e( 'and', 'email-subscribers' ); ?>"<?php echo ( ! $i ) ? ' style="display:none"' : ''; ?>>
249
 
@@ -342,7 +339,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
342
  <option value="0"><?php echo esc_html__( 'Any campaign', 'email-subscribers' ); ?></option>
343
  <?php if ( $all_campaigns ) : ?>
344
  <?php foreach ( $value_arr as $k => $v ) : ?>
345
- <?php
346
  foreach ( $all_campaigns as $campaign ) :
347
  ?>
348
  <option value="<?php echo esc_attr( $campaign['id'] ); ?>" <?php selected( $v, $campaign['id'] ); ?>><?php echo $campaign['name'] ? esc_html( $campaign['name'] ) : '[' . esc_html__( 'no title', 'email-subscribers' ) . '] (# ' . esc_attr( $campaign['id'] ) . ')'; ?></option>
@@ -355,11 +352,11 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
355
  <div class="ig-es-conditions-value-field" data-fields=",_lists__not_in,_lists__in,">
356
  <?php if ( $lists ) : ?>
357
  <select name="<?php echo esc_attr( $input_name ); ?>[<?php echo esc_attr( $i ); ?>][<?php echo esc_attr( $j ); ?>][value][]" class="condition-value <?php echo esc_attr( $select_list_class ); ?>" <?php echo esc_attr( $select_list_attr ); ?>>
358
- <?php
359
  if ( ES()->is_pro() ) :
360
  ?>
361
  <option value="0"><?php echo esc_html__( 'Any list', 'email-subscribers' ); ?></option>
362
- <?php
363
  endif;
364
  foreach ( $lists as $list_id => $list_name ) :
365
  ?>
@@ -390,7 +387,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
390
  </div>
391
 
392
  </div>
393
- <?php do_action( 'ig_es_upsell_campaign_rules'); ?>
394
  </div>
395
  </section>
396
  </div>
@@ -421,7 +418,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
421
  echo esc_html( ' ( ' );
422
  }
423
  echo wp_kses( '</span>', $allowedtags );
424
-
425
  }
426
  foreach ( $condition_group as $j => $condition ) :
427
  $field = isset( $condition['field'] ) ? $condition['field'] : ( isset( $condition[0] ) ? $condition[0] : '' );
@@ -439,14 +436,14 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
439
  <span class="ig-es-condition-type ig-es-condition-operator mt-1"><?php echo wp_kses( $nice['operator'], $allowedtags ); ?></span>
440
  <span class="ig-es-condition-type ig-es-condition-value mt-1 pl-2"><?php echo wp_kses( $nice['value'], $allowedtags ); ?></span>
441
  </div>
442
- <?php
443
- endforeach;
444
  if ( $i && count( $condition_group ) > 1 ) {
445
  echo '<span class="float-left pr-1 text-xs font-medium text-gray-400 tracking-wide uppercase mt-1">' . esc_html__( ') ', 'email-subscribers' ) . '</span>';
446
  }
447
  ?>
448
  </div>
449
- <?php
450
  endif;
451
  endforeach;
452
  ?>
@@ -459,7 +456,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
459
 
460
  /**
461
  * Get field operator
462
- *
463
  * @return string $operator Field operator
464
  */
465
  private function get_field_operator( $operator ) {
@@ -498,7 +495,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
498
 
499
  /**
500
  * Get condition HTML
501
- *
502
  * @return string Get condition HTML
503
  */
504
  private function get_condition_html( $condition, $formated = true ) {
@@ -519,8 +516,8 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
519
  if ( ! is_array( $value ) ) {
520
  $value = array( $value );
521
  }
522
- $urls = array();
523
- $campagins = array();
524
  $return['value'] = '<span class="font-medium text-gray-500 tracking-wide mr-1">' . $opening_quote . implode( $closing_quote . ' </span><span class="uppercase text-gray-400 pr-1 text-xs font-medium tracking-wide mt-1 mr-1">' . esc_html__( 'or', 'email-subscribers' ) . ' </span><span class="font-medium text-gray-500 tracking-wide mr-1"> ' . $opening_quote, array_map( array( $this, 'get_campaign_name' ), $value ) ) . $closing_quote . '</span>';
525
  } elseif ( isset( $this->campaign_rules['List'][ $field ] ) ) {
526
  if ( ! is_array( $value ) ) {
@@ -543,7 +540,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
543
 
544
  /**
545
  * Get names for field, operator and value
546
- *
547
  * @return string Formatted string
548
  */
549
  private function nice_name( $string, $type = null, $field = null ) {
@@ -576,17 +573,17 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
576
 
577
  /**
578
  * Get list of campaign rules
579
- *
580
  * @return array List of campaign rules
581
  */
582
  public static function get_campaign_rules() {
583
 
584
  $campaign_rules = array(
585
  'List' => array(
586
- '_lists__in' => array(
587
  'name' => esc_html__( 'is in List', 'email-subscribers' ),
588
  ),
589
- )
590
  );
591
 
592
  $campaign_rules = apply_filters( 'ig_es_campaign_rules', $campaign_rules );
@@ -596,7 +593,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
596
 
597
  /**
598
  * Get list of subscribers data based rules
599
- *
600
  * @return array List of subscribers data based rules
601
  */
602
  private function get_fields() {
@@ -610,24 +607,24 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
610
 
611
  /**
612
  * Get list of campaign related rules
613
- *
614
  * @return array List of aggregate campaigns related rules
615
  */
616
  private function get_campaign_related() {
617
  return array(
618
- '_sent' => esc_html__( 'has received', 'email-subscribers' ),
619
- '_sent__not_in' => esc_html__( 'has not received', 'email-subscribers' ),
620
- '_open' => esc_html__( 'has received and opened', 'email-subscribers' ),
621
- '_open__not_in' => esc_html__( 'has received but not opened', 'email-subscribers' ),
622
- '_click' => esc_html__( 'has received and clicked', 'email-subscribers' ),
623
- '_click__not_in' => esc_html__( 'has received and not clicked', 'email-subscribers' ),
624
  );
625
 
626
  }
627
 
628
  /**
629
  * Get list of aggregate campaigns related rules
630
- *
631
  * @return array List of aggregate campaigns related rules
632
  */
633
  private function get_aggregate_campaigns() {
@@ -644,7 +641,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
644
 
645
  /**
646
  * Get list of comparison operators
647
- *
648
  * @return array List of comparison operators
649
  */
650
  private function get_operators() {
@@ -667,7 +664,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
667
 
668
  /**
669
  * Get list of simple operators
670
- *
671
  * @return array Simple operators
672
  */
673
  private function get_simple_operators() {
@@ -684,7 +681,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
684
 
685
  /**
686
  * Get list of string operators
687
- *
688
  * @return array String operators
689
  */
690
  private function get_string_operators() {
@@ -703,7 +700,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
703
 
704
  /**
705
  * Get list of boolean operators
706
- *
707
  * @return array Boolean operator
708
  */
709
  private function get_bool_operators() {
@@ -716,9 +713,9 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
716
 
717
  /**
718
  * Get campaign name
719
- *
720
  * @param int $campaign_id Campaign ID
721
- *
722
  * @return string $name Campaign name
723
  */
724
  public function get_campaign_name( $campaign_id ) {
@@ -742,9 +739,9 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
742
 
743
  /**
744
  * Get list name
745
- *
746
  * @param int $list_id list ID
747
- *
748
  * @return string $list_name list name
749
  */
750
  public function get_list_name( $list_id ) {
@@ -757,25 +754,25 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
757
  $list_name = isset( $lists[ $list_id ] ) ? $lists[ $list_id ] : $list_id;
758
  return $list_name;
759
  }
760
-
761
  /**
762
  * Get country name
763
- *
764
  * @param string $code country code
765
- *
766
  * @return string $country_name country name
767
  */
768
  public function get_country_name( $code ) {
769
-
770
  $country_name = ES_Geolocation::get_countries_iso_code_name_map( $code );
771
  return $country_name;
772
  }
773
 
774
  /**
775
  * Remove empty conditions from campaign data
776
- *
777
  * @param array $conditions_data
778
- *
779
  * @return array $conditions_data
780
  */
781
  public static function remove_empty_conditions( $conditions_data = array() ) {
@@ -794,8 +791,7 @@ if ( ! class_exists( 'IG_ES_Campaign_Rules' ) ) {
794
  // Remove any empty value array.
795
  $conditions_data = array_values( array_filter( $list_conditions ) );
796
  }
797
-
798
-
799
  return $conditions_data;
800
  }
801
  }
16
 
17
  /**
18
  * Campaign rules
 
19
  */
20
  private $campaign_rules = array();
21
+
22
  /**
23
  * Subscriber related fields
 
24
  */
25
  private $fields = array();
26
 
28
  * Campaign related fields
29
  */
30
  private $campaign_related = array();
31
+
32
  /**
33
  * Aggregate campaigns fields
34
  */
35
  private $aggregate_campaigns = array();
36
+
37
  /**
38
  * Rule operators
39
  */
40
  private $operators = array();
41
+
42
  /**
43
  * Simple operators
44
  */
45
  private $simple_operators = array();
46
+
47
  /**
48
  * String operators
49
  */
50
  private $string_operators = array();
51
+
52
  /**
53
  * Boolean operators
54
  */
60
  public function __construct() {
61
  add_action( 'init', array( $this, 'init' ) );
62
  }
63
+
64
  /**
65
  * Initialize campaign rules
66
+ *
67
  * @since 4.6.12
68
  */
69
  public function init() {
75
  $this->string_operators = $this->get_string_operators();
76
  $this->bool_operators = $this->get_bool_operators();
77
  $this->campaign_rules = self::get_campaign_rules();
78
+
79
  add_action( 'ig_es_show_campaign_rules', array( $this, 'show_campaign_rules' ), 10, 2 );
80
  add_action( 'ig_es_campaign_show_conditions', array( $this, 'show_conditions' ) );
81
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
102
  * @since 4.6.11
103
  */
104
  public function show_campaign_rules( $campaign_id = 0, $campaign_data = array() ) {
105
+
106
  $current_page = ig_es_get_request_data( 'page' );
107
 
108
  $campaign_type = '';
111
  } else {
112
  $campaign_type = 'sequence_message';
113
  }
114
+
115
  $conditions = array();
116
  if ( ! empty( $campaign_data['meta'] ) ) {
117
  $campaign_meta = maybe_unserialize( $campaign_data['meta'] );
118
+ $conditions = ! empty( $campaign_meta['list_conditions'] ) ? $campaign_meta['list_conditions'] : array();
119
  }
120
 
121
  $args = array();
122
  if ( 'newsletter' === $campaign_type ) {
123
  $args = array(
124
  'include_types' => array(
125
+ 'newsletter',
126
  ),
127
+ 'status' => array(
128
  IG_ES_CAMPAIGN_STATUS_QUEUED,
129
+ IG_ES_CAMPAIGN_STATUS_FINISHED,
130
  ),
131
  );
132
  } else {
133
  $args = array(
134
  'include_types' => array(
135
+ 'sequence_message',
136
  ),
137
  );
138
  }
141
  $args['campaigns_not_in'] = array( $campaign_id );
142
  }
143
  $all_campaigns = ES()->campaigns_db->get_all_campaigns( $args );
144
+
145
  $lists = ES()->lists_db->get_list_id_name_map();
146
  if ( ! empty( $all_campaigns ) ) {
147
  $all_campaigns_stati = array_column( $all_campaigns, 'status' );
148
  }
149
 
150
  $countries_data = ES_Geolocation::get_countries();
151
+
152
  $input_name = 'es_newsletters' === $current_page ? 'broadcast_data[meta][list_conditions]' : 'seq_data[' . $campaign_id . '][list_conditions]';
153
 
154
+ $select_list_attr = ES()->is_pro() ? 'multiple="multiple"' : '';
155
+ $select_list_name = ES()->is_pro() ? 'broadcast_data[list_ids][]' : 'broadcast_data[list_ids]';
156
+ $select_list_class = ES()->is_pro() ? 'ig-es-campaign-rule-form-multiselect' : 'form-select';
157
 
158
  $sidebar_id = 'sidebar_' . $campaign_id;
159
  ?>
227
  <div class="ig-es-conditions px-6 h-full">
228
  <div class="ig-es-condition-container"></div>
229
  <div class="ig-es-conditions-wrap mt-1 mb-3 overflow-auto">
230
+ <?php
231
+
232
  array_unshift(
233
  $conditions,
234
  array(
240
  )
241
  );
242
 
243
+ foreach ( $conditions as $i => $condition_group ) :
 
244
  ?>
245
  <div class="ig-es-condition-group bg-white border border-gray-200 rounded-md my-2 pb-12 relative block px-4 rounded-lg pt-2 mt-2 mb-12" data-id="<?php echo esc_attr( $i ); ?>" data-operator="<?php esc_attr_e( 'and', 'email-subscribers' ); ?>"<?php echo ( ! $i ) ? ' style="display:none"' : ''; ?>>
246
 
339
  <option value="0"><?php echo esc_html__( 'Any campaign', 'email-subscribers' ); ?></option>
340
  <?php if ( $all_campaigns ) : ?>
341
  <?php foreach ( $value_arr as $k => $v ) : ?>
342
+ <?php
343
  foreach ( $all_campaigns as $campaign ) :
344
  ?>
345
  <option value="<?php echo esc_attr( $campaign['id'] ); ?>" <?php selected( $v, $campaign['id'] ); ?>><?php echo $campaign['name'] ? esc_html( $campaign['name'] ) : '[' . esc_html__( 'no title', 'email-subscribers' ) . '] (# ' . esc_attr( $campaign['id'] ) . ')'; ?></option>
352
  <div class="ig-es-conditions-value-field" data-fields=",_lists__not_in,_lists__in,">
353
  <?php if ( $lists ) : ?>
354
  <select name="<?php echo esc_attr( $input_name ); ?>[<?php echo esc_attr( $i ); ?>][<?php echo esc_attr( $j ); ?>][value][]" class="condition-value <?php echo esc_attr( $select_list_class ); ?>" <?php echo esc_attr( $select_list_attr ); ?>>
355
+ <?php
356
  if ( ES()->is_pro() ) :
357
  ?>
358
  <option value="0"><?php echo esc_html__( 'Any list', 'email-subscribers' ); ?></option>
359
+ <?php
360
  endif;
361
  foreach ( $lists as $list_id => $list_name ) :
362
  ?>
387
  </div>
388
 
389
  </div>
390
+ <?php do_action( 'ig_es_upsell_campaign_rules' ); ?>
391
  </div>
392
  </section>
393
  </div>
418
  echo esc_html( ' ( ' );
419
  }
420
  echo wp_kses( '</span>', $allowedtags );
421
+
422
  }
423
  foreach ( $condition_group as $j => $condition ) :
424
  $field = isset( $condition['field'] ) ? $condition['field'] : ( isset( $condition[0] ) ? $condition[0] : '' );
436
  <span class="ig-es-condition-type ig-es-condition-operator mt-1"><?php echo wp_kses( $nice['operator'], $allowedtags ); ?></span>
437
  <span class="ig-es-condition-type ig-es-condition-value mt-1 pl-2"><?php echo wp_kses( $nice['value'], $allowedtags ); ?></span>
438
  </div>
439
+ <?php
440
+ endforeach;
441
  if ( $i && count( $condition_group ) > 1 ) {
442
  echo '<span class="float-left pr-1 text-xs font-medium text-gray-400 tracking-wide uppercase mt-1">' . esc_html__( ') ', 'email-subscribers' ) . '</span>';
443
  }
444
  ?>
445
  </div>
446
+ <?php
447
  endif;
448
  endforeach;
449
  ?>
456
 
457
  /**
458
  * Get field operator
459
+ *
460
  * @return string $operator Field operator
461
  */
462
  private function get_field_operator( $operator ) {
495
 
496
  /**
497
  * Get condition HTML
498
+ *
499
  * @return string Get condition HTML
500
  */
501
  private function get_condition_html( $condition, $formated = true ) {
516
  if ( ! is_array( $value ) ) {
517
  $value = array( $value );
518
  }
519
+ $urls = array();
520
+ $campagins = array();
521
  $return['value'] = '<span class="font-medium text-gray-500 tracking-wide mr-1">' . $opening_quote . implode( $closing_quote . ' </span><span class="uppercase text-gray-400 pr-1 text-xs font-medium tracking-wide mt-1 mr-1">' . esc_html__( 'or', 'email-subscribers' ) . ' </span><span class="font-medium text-gray-500 tracking-wide mr-1"> ' . $opening_quote, array_map( array( $this, 'get_campaign_name' ), $value ) ) . $closing_quote . '</span>';
522
  } elseif ( isset( $this->campaign_rules['List'][ $field ] ) ) {
523
  if ( ! is_array( $value ) ) {
540
 
541
  /**
542
  * Get names for field, operator and value
543
+ *
544
  * @return string Formatted string
545
  */
546
  private function nice_name( $string, $type = null, $field = null ) {
573
 
574
  /**
575
  * Get list of campaign rules
576
+ *
577
  * @return array List of campaign rules
578
  */
579
  public static function get_campaign_rules() {
580
 
581
  $campaign_rules = array(
582
  'List' => array(
583
+ '_lists__in' => array(
584
  'name' => esc_html__( 'is in List', 'email-subscribers' ),
585
  ),
586
+ ),
587
  );
588
 
589
  $campaign_rules = apply_filters( 'ig_es_campaign_rules', $campaign_rules );
593
 
594
  /**
595
  * Get list of subscribers data based rules
596
+ *
597
  * @return array List of subscribers data based rules
598
  */
599
  private function get_fields() {
607
 
608
  /**
609
  * Get list of campaign related rules
610
+ *
611
  * @return array List of aggregate campaigns related rules
612
  */
613
  private function get_campaign_related() {
614
  return array(
615
+ '_sent' => esc_html__( 'has received', 'email-subscribers' ),
616
+ '_sent__not_in' => esc_html__( 'has not received', 'email-subscribers' ),
617
+ '_open' => esc_html__( 'has received and opened', 'email-subscribers' ),
618
+ '_open__not_in' => esc_html__( 'has received but not opened', 'email-subscribers' ),
619
+ '_click' => esc_html__( 'has received and clicked', 'email-subscribers' ),
620
+ '_click__not_in' => esc_html__( 'has received and not clicked', 'email-subscribers' ),
621
  );
622
 
623
  }
624
 
625
  /**
626
  * Get list of aggregate campaigns related rules
627
+ *
628
  * @return array List of aggregate campaigns related rules
629
  */
630
  private function get_aggregate_campaigns() {
641
 
642
  /**
643
  * Get list of comparison operators
644
+ *
645
  * @return array List of comparison operators
646
  */
647
  private function get_operators() {
664
 
665
  /**
666
  * Get list of simple operators
667
+ *
668
  * @return array Simple operators
669
  */
670
  private function get_simple_operators() {
681
 
682
  /**
683
  * Get list of string operators
684
+ *
685
  * @return array String operators
686
  */
687
  private function get_string_operators() {
700
 
701
  /**
702
  * Get list of boolean operators
703
+ *
704
  * @return array Boolean operator
705
  */
706
  private function get_bool_operators() {
713
 
714
  /**
715
  * Get campaign name
716
+ *
717
  * @param int $campaign_id Campaign ID
718
+ *
719
  * @return string $name Campaign name
720
  */
721
  public function get_campaign_name( $campaign_id ) {
739
 
740
  /**
741
  * Get list name
742
+ *
743
  * @param int $list_id list ID
744
+ *
745
  * @return string $list_name list name
746
  */
747
  public function get_list_name( $list_id ) {
754
  $list_name = isset( $lists[ $list_id ] ) ? $lists[ $list_id ] : $list_id;
755
  return $list_name;
756
  }
757
+
758
  /**
759
  * Get country name
760
+ *
761
  * @param string $code country code
762
+ *
763
  * @return string $country_name country name
764
  */
765
  public function get_country_name( $code ) {
766
+
767
  $country_name = ES_Geolocation::get_countries_iso_code_name_map( $code );
768
  return $country_name;
769
  }
770
 
771
  /**
772
  * Remove empty conditions from campaign data
773
+ *
774
  * @param array $conditions_data
775
+ *
776
  * @return array $conditions_data
777
  */
778
  public static function remove_empty_conditions( $conditions_data = array() ) {
791
  // Remove any empty value array.
792
  $conditions_data = array_values( array_filter( $list_conditions ) );
793
  }
794
+
 
795
  return $conditions_data;
796
  }
797
  }
lite/admin/class-ig-es-onboarding.php CHANGED
@@ -16,10 +16,9 @@ if ( ! defined( 'ABSPATH' ) ) {
16
 
17
 
18
  if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
19
-
20
  /**
21
  * The onboarding-specific functionality of the plugin.
22
- *
23
  */
24
  class IG_ES_Onboarding {
25
 
@@ -29,27 +28,25 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
29
  * @var Onboarding instance
30
  */
31
  protected static $instance = null;
32
-
33
  /**
34
  * Added Logger Context
35
  *
36
  * @since 4.6.0
37
  * @var array
38
- *
39
  */
40
  protected static $logger_context = array(
41
- 'source' => 'ig_es_onboarding'
42
  );
43
-
44
  /**
45
  * Variable to hold all onboarding tasks list
46
  *
47
  * @since 4.6.0
48
  * @var array
49
- *
50
  */
51
  private static $all_onboarding_tasks = array(
52
- 'configuration_tasks' => array(
53
  'set_settings',
54
  'create_default_lists',
55
  'create_contacts_and_add_to_list',
@@ -65,68 +62,62 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
65
  'check_test_email_on_server',
66
  'evaluate_email_delivery',
67
  ),
68
- 'completion_tasks' => array(
69
  'subscribe_to_es',
70
  'save_final_configuration',
71
- )
72
  );
73
 
74
  /**
75
  * Option name for current task name.
76
- *
77
  * @since 4.6.0
78
  * @var array
79
- *
80
  */
81
  private static $onboarding_current_task_option = 'ig_es_onboarding_current_task';
82
 
83
  /**
84
  * Option name which holds common data between tasks.
85
- *
86
  * E.g. created subscription form id from create_default_subscription_form function so we can use it in add_widget_to_sidebar
87
  *
88
  * @since 4.6.0
89
  * @var array
90
- *
91
  */
92
  private static $onboarding_tasks_data_option = 'ig_es_onboarding_tasks_data';
93
 
94
  /**
95
  * Option name which holds tasks which are done.
96
- *
97
  * @since 4.6.0
98
  * @var array
99
- *
100
  */
101
  private static $onboarding_tasks_done_option = 'ig_es_onboarding_tasks_done';
102
-
103
  /**
104
  * Option name which holds tasks which are failed.
105
- *
106
  * @since 4.6.0
107
  * @var array
108
- *
109
  */
110
  private static $onboarding_tasks_failed_option = 'ig_es_onboarding_tasks_failed';
111
 
112
  /**
113
  * Option name which holds tasks which are skipped due to dependency on other tasks.
114
- *
115
  * @since 4.6.0
116
  * @var array
117
- *
118
  */
119
  private static $onboarding_tasks_skipped_option = 'ig_es_onboarding_tasks_skipped';
120
 
121
  /**
122
  * Option name which store the step which has been completed.
123
- *
124
  * @since 4.6.0
125
  * @var string
126
- *
127
  */
128
  private static $onboarding_step_option = 'ig_es_onboarding_step';
129
-
130
  /**
131
  * Initialize the class and set its properties.
132
  *
@@ -136,10 +127,10 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
136
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
137
  add_action( 'wp_ajax_ig_es_handle_request', array( $this, 'handle_request' ) );
138
  }
139
-
140
  /**
141
  * Get class instance.
142
- *
143
  * @since 4.6.0
144
  */
145
  public static function instance() {
@@ -148,14 +139,14 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
148
  }
149
  return self::$instance;
150
  }
151
-
152
  /**
153
  * Register the JavaScript for the onboarding process.
154
- *
155
  * @since 4.6.0
156
  */
157
  public function enqueue_scripts() {
158
-
159
  if ( ! ES()->is_es_admin_screen() ) {
160
  return;
161
  }
@@ -173,14 +164,14 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
173
  }
174
  }
175
  }
176
-
177
  /**
178
  * Method to perform configuration and list, ES form, campaigns creation related operations in the onboarding
179
- *
180
  * @since 4.6.0
181
  */
182
  public function handle_request() {
183
-
184
  $response = array();
185
 
186
  check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' );
@@ -196,10 +187,10 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
196
 
197
  wp_send_json( $response );
198
  }
199
-
200
  /**
201
  * Method to perform configuration and list, ES form, campaigns creation related operations in the onboarding
202
- *
203
  * @since 4.6.0
204
  */
205
  public function ajax_perform_configuration_tasks() {
@@ -210,7 +201,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
210
 
211
  /**
212
  * Method to perform email delivery tasks.
213
- *
214
  * @since 4.6.0
215
  */
216
  public function ajax_queue_default_broadcast_newsletter() {
@@ -219,7 +210,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
219
 
220
  /**
221
  * Method to perform email delivery tasks.
222
- *
223
  * @since 4.6.0
224
  */
225
  public function ajax_dispatch_emails_from_server() {
@@ -228,7 +219,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
228
 
229
  /**
230
  * Method to perform email delivery tasks.
231
- *
232
  * @since 4.6.0
233
  */
234
  public function ajax_check_test_email_on_server() {
@@ -238,7 +229,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
238
 
239
  /**
240
  * Method to perform email delivery tasks.
241
- *
242
  * @since 4.6.0
243
  */
244
  public function ajax_checking_spam_score_delivery_metrics() {
@@ -247,16 +238,16 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
247
 
248
  /**
249
  * Method to perform email delivery tasks.
250
- *
251
  * @since 4.6.0
252
  */
253
  public function ajax_evaluate_email_delivery() {
254
  return $this->perform_onboarding_tasks( 'email_delivery_check_tasks', 'evaluate_email_delivery' );
255
  }
256
-
257
  /**
258
  * Method to perform email delivery tasks.
259
- *
260
  * @since 4.6.0
261
  */
262
  public function ajax_finishing_onboarding() {
@@ -266,17 +257,17 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
266
  // Delete the onboarding data used during onboarding process.
267
  $this->delete_onboarding_data();
268
 
269
- $dashboard_url = admin_url( 'admin.php?page=es_dashboard' );
270
  $response['redirect_url'] = $dashboard_url;
271
-
272
  return $response;
273
  }
274
 
275
  /**
276
  * Method to updatee the onboarding step
277
- *
278
- * @return bool
279
- *
280
  * @since 4.6.0
281
  */
282
  public static function ajax_update_onboarding_step() {
@@ -296,10 +287,10 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
296
 
297
  /**
298
  * Method to perform give onboarding tasks types.
299
- *
300
  * @param string $task_group Tasks group
301
  * @param string $task_name Specific task
302
- *
303
  * @since 4.6.0
304
  */
305
  public function perform_onboarding_tasks( $task_group = '', $task_name = '' ) {
@@ -328,13 +319,13 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
328
  }
329
 
330
  $onboarding_tasks_done = get_option( self::$onboarding_tasks_done_option, array() );
331
- $current_tasks_done = ! empty( $onboarding_tasks_done[$task_group] ) ? $onboarding_tasks_done[$task_group] : array();
332
-
333
  $onboarding_tasks_failed = get_option( self::$onboarding_tasks_failed_option, array() );
334
- $current_tasks_failed = ! empty( $onboarding_tasks_failed[$task_group] ) ? $onboarding_tasks_failed[$task_group] : array();
335
 
336
  $onboarding_tasks_skipped = get_option( self::$onboarding_tasks_skipped_option, array() );
337
- $current_tasks_skipped = ! empty( $onboarding_tasks_skipped[$task_group] ) ? $onboarding_tasks_skipped[$task_group] : array();
338
 
339
  $onboarding_tasks_data = get_option( self::$onboarding_tasks_data_option, array() );
340
  if ( ! empty( $current_tasks ) ) {
@@ -348,10 +339,10 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
348
  $task_response = call_user_func( array( $this, $current_task ) );
349
  if ( 'success' === $task_response['status'] ) {
350
  if ( ! empty( $task_response['tasks_data'] ) ) {
351
- if ( ! isset( $onboarding_tasks_data[$current_task] ) ) {
352
- $onboarding_tasks_data[$current_task] = array();
353
  }
354
- $onboarding_tasks_data[$current_task] = array_merge( $onboarding_tasks_data[$current_task], $task_response['tasks_data'] );
355
  }
356
  $logger->info( 'Task Done:' . $current_task, self::$logger_context );
357
  // Set success status only if not already set else it can override error/skipped statuses set previously from other tasks.
@@ -360,19 +351,19 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
360
  }
361
  $current_tasks_done[] = $current_task;
362
  } elseif ( 'skipped' === $task_response['status'] ) {
363
- $response['status'] = 'skipped';
364
  $current_tasks_skipped[] = $current_task;
365
  } else {
366
  $logger->info( 'Task Failed:' . $current_task, self::$logger_context );
367
- $response['status'] = 'error';
368
  $current_tasks_failed[] = $current_task;
369
  }
370
-
371
- $response['tasks'][$current_task] = $task_response;
372
 
373
- $onboarding_tasks_done[$task_group] = $current_tasks_done;
374
- $onboarding_tasks_failed[$task_group] = $current_tasks_failed;
375
- $onboarding_tasks_skipped[$task_group] = $current_tasks_skipped;
 
 
376
 
377
  update_option( self::$onboarding_tasks_done_option, $onboarding_tasks_done );
378
  update_option( self::$onboarding_tasks_failed_option, $onboarding_tasks_failed );
@@ -383,7 +374,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
383
  $logger->info( 'Missing Task:' . $current_task, self::$logger_context );
384
  }
385
  } else {
386
- $response['tasks'][$current_task] = array(
387
  'status' => 'success',
388
  );
389
  $logger->info( 'Task already done:' . $current_task, self::$logger_context );
@@ -396,7 +387,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
396
 
397
  /**
398
  * Set settings required for ES settings.
399
- *
400
  * @since 4.6.0
401
  */
402
  public function set_settings() {
@@ -408,7 +399,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
408
  $from_name = ig_es_get_request_data( 'es_from_name', '' );
409
  $from_email = ig_es_get_request_data( 'es_from_email', '' );
410
  $enable_double_optin = ig_es_get_request_data( 'enable_double_optin', 'yes' );
411
- $optin_type = 'yes' === $enable_double_optin ? 'double_opt_in': 'single_opt_in';
412
  $is_trial = ig_es_get_request_data( 'is_trial', '' );
413
  $allow_tracking = ig_es_get_request_data( 'allow_tracking', '' );
414
 
@@ -440,12 +431,12 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
440
  * @since 4.0.0
441
  */
442
  public function create_default_lists() {
443
-
444
  $response = array(
445
  'status' => 'error',
446
  );
447
-
448
- $default_list = ES()->lists_db->get_list_by_name( IG_DEFAULT_LIST );
449
  // Check if list already not exists.
450
  if ( empty( $default_list['id'] ) ) {
451
  // Add default list.
@@ -453,7 +444,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
453
  } else {
454
  $default_list_id = $default_list['id'];
455
  }
456
-
457
  $main_list = ES()->lists_db->get_list_by_name( IG_MAIN_LIST );
458
  // Check if list already not exists.
459
  if ( empty( $main_list['id'] ) ) {
@@ -469,12 +460,12 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
469
  } else {
470
  /* translators: 1. Main list name. 2. Default list name. */
471
  $response['message'] = sprintf( __( 'Unable to create %1$s and %2$s list.', 'email-subscribers' ), IG_MAIN_LIST, IG_DEFAULT_LIST );
472
- $response['status'] = 'error';
473
  }
474
 
475
  return $response;
476
  }
477
-
478
  public function create_contacts_and_add_to_list() {
479
 
480
  // Flush cache to make sure we get data from DB instead of cache
@@ -516,12 +507,12 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
516
  'status' => 'verified',
517
  'unsubscribed' => 0,
518
  'hash' => ES_Common::generate_guid(),
519
- 'created_at' => ig_get_current_date_time()
520
  );
521
 
522
  $contact_id = ES()->contacts_db->insert( $data );
523
  if ( $contact_id ) {
524
-
525
  // Prepare admin contact list data.
526
  $data = array(
527
  'contact_id' => $contact_id,
@@ -560,7 +551,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
560
  'status' => 'verified',
561
  'unsubscribed' => 0,
562
  'hash' => ES_Common::generate_guid(),
563
- 'created_at' => ig_get_current_date_time()
564
  );
565
  $contact_id = ES()->contacts_db->insert( $data );
566
  if ( $contact_id ) {
@@ -571,7 +562,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
571
  'subscribed_at' => ig_get_current_date_time(),
572
  'subscribed_ip' => null,
573
  );
574
-
575
  $contacts_added = ES()->lists_contacts_db->add_contact_to_lists( $data, $default_list_id );
576
  if ( $contacts_added ) {
577
  $response['status'] = 'success';
@@ -585,9 +576,9 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
585
 
586
  /**
587
  * Add user registration workflow
588
- *
589
  * @return $response
590
- *
591
  * @since 4.6.0
592
  */
593
  public function add_workflow_for_user_registration() {
@@ -599,7 +590,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
599
  $workflow_query_args = array(
600
  'trigger_name' => 'ig_es_user_registered',
601
  );
602
-
603
  $workflows = ES()->workflows_db->get_workflows( $workflow_query_args );
604
 
605
  // Add workflow only if there is no workflow for user registration already present.
@@ -615,7 +606,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
615
  $workflow_meta = array();
616
  $workflow_meta['when_to_run'] = 'immediately';
617
  $workflow_status = 0;
618
-
619
  $workflow_actions = array(
620
  array(
621
  'action_name' => 'ig_es_add_to_list',
@@ -642,7 +633,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
642
 
643
  return $response;
644
  }
645
-
646
  /**
647
  * Create default form
648
  *
@@ -658,66 +649,66 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
658
  $default_list = ES()->lists_db->get_list_by_name( IG_MAIN_LIST );
659
  $list_id = $default_list['id'];
660
 
661
- $body = array(
662
  array(
663
- 'type' => 'text',
664
- 'name' => 'Name',
665
- 'id' => 'name',
666
- 'params' => array(
667
  'label' => 'Name',
668
  'show' => true,
669
- 'required' => true
670
  ),
671
 
672
- 'position' => 1
673
  ),
674
 
675
  array(
676
- 'type' => 'text',
677
- 'name' => 'Email',
678
- 'id' => 'email',
679
- 'params' => array(
680
  'label' => 'Email',
681
  'show' => true,
682
- 'required' => true
683
  ),
684
 
685
- 'position' => 2
686
  ),
687
 
688
  array(
689
- 'type' => 'checkbox',
690
- 'name' => 'Lists',
691
- 'id' => 'lists',
692
- 'params' => array(
693
  'label' => 'Lists',
694
  'show' => false,
695
  'required' => true,
696
- 'values' => array( $list_id )
697
  ),
698
 
699
- 'position' => 3
700
  ),
701
 
702
  array(
703
- 'type' => 'submit',
704
- 'name' => 'submit',
705
- 'id' => 'submit',
706
- 'params' => array(
707
  'label' => 'Subscribe',
708
- 'show' => true
709
  ),
710
 
711
- 'position' => 4
712
  ),
713
 
714
  );
715
 
716
  $settings = array(
717
  'lists' => array( $list_id ),
718
- 'desc' => ''
719
  );
720
-
721
  $add_gdpr_consent = ig_es_get_request_data( 'add_gdpr_consent', '' );
722
 
723
  // Add GDPR setting if admin has opted for.
@@ -738,9 +729,9 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
738
  // Add Form.
739
  $form_id = ES()->forms_db->add_form( $form_data );
740
  if ( ! empty( $form_id ) ) {
741
- $response['status'] = 'success';
742
  $response['tasks_data'] = array(
743
- 'form_id' => $form_id
744
  );
745
  } else {
746
  $response['status'] = 'error';
@@ -748,10 +739,10 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
748
 
749
  return $response;
750
  }
751
-
752
  /**
753
  * Add ES widget to active sidebar
754
- *
755
  * @since 4.6.0
756
  */
757
  public function add_widget_to_sidebar() {
@@ -769,15 +760,15 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
769
  $onboarding_tasks_data = get_option( self::$onboarding_tasks_data_option, array() );
770
  // Get created form id from create_default_subscription_form task's data.
771
  if ( ! empty( $onboarding_tasks_data['create_default_subscription_form']['form_id'] ) ) {
772
- $form_id = $onboarding_tasks_data['create_default_subscription_form']['form_id'];
773
- $widget_data = array(
774
  'form_id' => $form_id,
775
  );
776
  $widget_added = ig_es_insert_widget_in_sidebar( 'email-subscribers-form', $widget_data, $sidebar_id );
777
  if ( $widget_added ) {
778
  $response['status'] = 'success';
779
  $response['tasks_data'] = array(
780
- 'sidebar_id' => $sidebar_id,
781
  'sidebar_name' => $sidebar['name'],
782
  );
783
  /* translators: Active sidebar name. */
@@ -795,10 +786,10 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
795
  }
796
  }
797
  }
798
-
799
  return $response;
800
  }
801
-
802
  /**
803
  * Create and send default broadcast while onboarding
804
  *
@@ -821,10 +812,10 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
821
 
822
  // First Create Default Template.
823
  // Start-IG-Code.
824
- $sample = '<strong style="color: #990000">What can you achieve using Email Subscribers?</strong><p>Add subscription forms on website, send HTML newsletters & automatically notify subscribers about new blog posts once it is published.';
825
  // End-IG-Code.
826
  // Start-Woo-Code.
827
- $sample = '<strong style="color: #990000">What can you achieve using Email Subscribers?</strong><p>Add subscription forms on website, send HTML newsletters.';
828
  // End-Woo-Code.
829
  $sample .= ' You can also Import or Export subscribers from any list to Email Subscribers.</p>';
830
  $sample .= ' <strong style="color: #990000">Plugin Features</strong><ol>';
@@ -850,8 +841,8 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
850
  'post_status' => 'publish',
851
  'post_type' => 'es_template',
852
  'meta_input' => array(
853
- 'es_template_type' => 'newsletter'
854
- )
855
  );
856
 
857
  // Insert the post into the database
@@ -871,9 +862,9 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
871
  $data['subject'] = $subject;
872
  $data['type'] = 'newsletter';
873
  $data['from_email'] = $from_email;
874
- $data['reply_to_email'] = $from_email;
875
  $data['from_name'] = $from_name;
876
- $data['reply_to_name'] = $from_name;
877
  $data['list_ids'] = $list_id;
878
  $data['base_template_id'] = $post_id;
879
  $data['body'] = $sample;
@@ -887,7 +878,6 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
887
  'broadcast_id' => $broadcast_id,
888
  );
889
  }
890
-
891
  }
892
  }
893
 
@@ -896,9 +886,9 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
896
 
897
  /**
898
  * Method to queue created default newsletter broadcast.
899
- *
900
  * @since 4.6.0
901
- */
902
  public function queue_default_broadcast_newsletter() {
903
 
904
  $response = array(
@@ -906,8 +896,8 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
906
  );
907
 
908
  $onboarding_tasks_data = get_option( self::$onboarding_tasks_data_option, array() );
909
- $campaign_id = ! empty( $onboarding_tasks_data['create_default_newsletter_broadcast']['broadcast_id'] ) ? $onboarding_tasks_data['create_default_newsletter_broadcast']['broadcast_id']: 0;
910
-
911
  if ( ! empty( $campaign_id ) ) {
912
  $default_list = ES()->lists_db->get_list_by_name( IG_DEFAULT_LIST );
913
  if ( ! empty( $default_list ) ) {
@@ -915,7 +905,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
915
  $subscribers = ES()->contacts_db->get_active_contacts_by_list_id( $list_id );
916
  if ( ! empty( $subscribers ) && count( $subscribers ) > 0 ) {
917
  $content_body = ES()->campaigns_db->get_column( 'body', $campaign_id );
918
- $title = ES()->campaigns_db->get_column( 'name', $campaign_id );
919
  $guid = ES_Common::generate_guid( 6 );
920
  $now = ig_get_current_date_time();
921
 
@@ -931,9 +921,9 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
931
  'created_at' => $now,
932
  'updated_at' => $now,
933
  );
934
-
935
  $report_id = ES_DB_Mailing_Queue::add_notification( $data );
936
-
937
  $delivery_data = array();
938
  $delivery_data['hash'] = $guid;
939
  $delivery_data['subscribers'] = $subscribers;
@@ -956,7 +946,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
956
 
957
  /**
958
  * Method to send default broadcast campaign.
959
- *
960
  * @since 4.6.0
961
  */
962
  public function dispatch_emails_from_server() {
@@ -967,17 +957,17 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
967
 
968
  // Send test email to Icegram API only if trial is valid or user is premium user.
969
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
970
-
971
  $service = new ES_Send_Test_Email();
972
  $res = $service->send_test_email();
973
  }
974
 
975
  $onboarding_tasks_data = get_option( self::$onboarding_tasks_data_option, array() );
976
- $campaign_id = ! empty( $onboarding_tasks_data['create_default_newsletter_broadcast']['broadcast_id'] ) ? $onboarding_tasks_data['create_default_newsletter_broadcast']['broadcast_id']: 0;
977
  $report_id = ! empty( $onboarding_tasks_data['queue_default_broadcast_newsletter']['report_id'] ) ? $onboarding_tasks_data['queue_default_broadcast_newsletter']['report_id'] : 0;
978
-
979
  if ( ! empty( $campaign_id ) && ! empty( $report_id ) ) {
980
-
981
  $content_body = ES()->campaigns_db->get_column( 'body', $campaign_id );
982
  $title = ES()->campaigns_db->get_column( 'name', $campaign_id );
983
  $email_created = time();
@@ -1013,7 +1003,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1013
  update_option( 'ig_es_onboarding_test_campaign_success', 'yes' );
1014
  } else {
1015
  $response['status'] = 'error';
1016
- $response['message'] = ! empty( $res['message'] ) ? $res['message']: '';
1017
  $response['additional_message'] = __( 'Seems like your server is not setup correctly to send emails. Please confirm if you\'re getting any other emails from within WordPress', 'email-subscribers' );
1018
  update_option( 'ig_es_onboarding_test_campaign_error', 'yes' );
1019
  }
@@ -1025,7 +1015,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1025
 
1026
  /**
1027
  * Method to check test email on Icegram servers.
1028
- *
1029
  * @since 4.6.0
1030
  */
1031
  public function check_test_email_on_server() {
@@ -1037,8 +1027,8 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1037
  // Check test email only if user has valid trial or is a premium user.
1038
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
1039
  $onboarding_tasks_failed = get_option( self::$onboarding_tasks_failed_option, array() );
1040
- $email_delivery_check_tasks_failed = ! empty( $onboarding_tasks_failed['email_delivery_check_tasks'] ) ? $onboarding_tasks_failed['email_delivery_check_tasks']: array();
1041
-
1042
  // Peform test email checking if dispatch_emails_from_server task hasn't failed.
1043
  if ( ! in_array( 'dispatch_emails_from_server', $email_delivery_check_tasks_failed, true ) ) {
1044
  $service = new ES_Email_Delivery_Check();
@@ -1053,7 +1043,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1053
 
1054
  /**
1055
  * Method to check spam score of test email recieved on Icegram servers.
1056
- *
1057
  * @since 4.6.0
1058
  */
1059
  public function checking_spam_score_delivery_metrics() {
@@ -1065,10 +1055,10 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1065
  // Check spam score only if user has valid trial or is a premium user.
1066
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
1067
  $onboarding_tasks_failed = get_option( self::$onboarding_tasks_failed_option, array() );
1068
- $email_delivery_check_tasks_failed = ! empty( $onboarding_tasks_failed['email_delivery_check_tasks'] ) ? $onboarding_tasks_failed['email_delivery_check_tasks']: array();
1069
 
1070
  $onboarding_tasks_skipped = get_option( self::$onboarding_tasks_skipped_option, array() );
1071
- $email_delivery_check_tasks_skipped = ! empty( $onboarding_tasks_skipped['email_delivery_check_tasks'] ) ? $onboarding_tasks_skipped['email_delivery_check_tasks']: array();
1072
 
1073
  // Peform test email spam score only if check_test_email_on_server task hasn't failed or skipped.
1074
  if ( ! in_array( 'check_test_email_on_server', $email_delivery_check_tasks_failed, true ) && ! in_array( 'check_test_email_on_server', $email_delivery_check_tasks_skipped, true ) ) {
@@ -1083,7 +1073,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1083
 
1084
  /**
1085
  * Method to check test email on Icegram servers.
1086
- *
1087
  * @since 4.6.0
1088
  */
1089
  public function evaluate_email_delivery() {
@@ -1095,10 +1085,10 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1095
  // Evaluate email delivery only if user has valid trial or is a premium user.
1096
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
1097
  $onboarding_tasks_failed = get_option( self::$onboarding_tasks_failed_option, array() );
1098
- $email_delivery_check_tasks_failed = ! empty( $onboarding_tasks_failed['email_delivery_check_tasks'] ) ? $onboarding_tasks_failed['email_delivery_check_tasks']: array();
1099
 
1100
  $onboarding_tasks_skipped = get_option( self::$onboarding_tasks_skipped_option, array() );
1101
- $email_delivery_check_tasks_skipped = ! empty( $onboarding_tasks_skipped['email_delivery_check_tasks'] ) ? $onboarding_tasks_skipped['email_delivery_check_tasks']: array();
1102
 
1103
  // Peform email delivery evaulation only if check_test_email_on_server task hasn't failed or skipped.
1104
  if ( ! in_array( 'check_test_email_on_server', $email_delivery_check_tasks_failed, true ) && ! in_array( 'check_test_email_on_server', $email_delivery_check_tasks_skipped, true ) ) {
@@ -1109,7 +1099,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1109
  }
1110
  return $response;
1111
  }
1112
-
1113
  /**
1114
  * Create default Post notification while on boarding
1115
  *
@@ -1118,8 +1108,8 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1118
  * @since 4.6.0
1119
  */
1120
  public function create_default_post_notification() {
1121
-
1122
- $response = array(
1123
  'status' => 'error',
1124
  );
1125
  $create_post_notification = ig_es_get_request_data( 'create_post_notification', '' );
@@ -1148,8 +1138,8 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1148
  'post_status' => 'publish',
1149
  'post_type' => 'es_template',
1150
  'meta_input' => array(
1151
- 'es_template_type' => 'post_notification'
1152
- )
1153
  );
1154
  // Insert the post into the database
1155
  $post_id = wp_insert_post( $post );
@@ -1159,10 +1149,12 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1159
  if ( ! empty( $post_id ) ) {
1160
  $list_id = $default_list['id'];
1161
 
1162
- $categories_objects = get_terms( array(
1163
- 'taxonomy' => 'category',
1164
- 'hide_empty' => false,
1165
- ) );
 
 
1166
 
1167
  $categories = array();
1168
  if ( count( $categories_objects ) > 0 ) {
@@ -1189,9 +1181,9 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1189
 
1190
  $post_notification_id = ES()->campaigns_db->save_campaign( $data );
1191
  if ( $post_notification_id ) {
1192
- $response['status'] = 'success';
1193
  $response['tasks_data'] = array(
1194
- 'post_notification_id' => $post_notification_id
1195
  );
1196
  }
1197
  }
@@ -1201,13 +1193,13 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1201
 
1202
  /**
1203
  * Method to subscribe to klawoo in the onboarding process.
1204
- *
1205
  * @since 4.6.0
1206
- */
1207
  public function subscribe_to_es() {
1208
 
1209
  $response = array(
1210
- 'status' => 'error'
1211
  );
1212
 
1213
  $name = ig_es_get_request_data( 'name', '' );
@@ -1215,7 +1207,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1215
  $list = ig_es_get_request_data( 'list', '' );
1216
 
1217
  if ( ! empty( $list ) && is_email( $email ) ) {
1218
-
1219
  $url_params = array(
1220
  'ig_es_external_action' => 'subscribe',
1221
  'name' => $name,
@@ -1230,7 +1222,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1230
 
1231
  $ig_es_url = 'https://www.icegram.com/';
1232
  $ig_es_url = add_query_arg( $url_params, $ig_es_url );
1233
-
1234
  // Make a get request.
1235
  $api_response = wp_remote_get( $ig_es_url );
1236
  if ( ! is_wp_error( $api_response ) ) {
@@ -1249,9 +1241,9 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1249
 
1250
  /**
1251
  * Method to subscribe to klawoo in the onboarding process.
1252
- *
1253
  * @since 4.6.0
1254
- */
1255
  public function save_final_configuration() {
1256
 
1257
  $response = array();
@@ -1281,7 +1273,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1281
  );
1282
 
1283
  $onboarding_options = $this->get_onboarding_data_options();
1284
-
1285
  foreach ( $onboarding_options as $option ) {
1286
  $deleted = delete_option( $option );
1287
  }
@@ -1293,7 +1285,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1293
 
1294
  /**
1295
  * Method to get the onboarding data options used in onboarding process.
1296
- *
1297
  * @since 4.6.0
1298
  */
1299
  public function get_onboarding_data_options() {
@@ -1312,18 +1304,18 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1312
 
1313
  /**
1314
  * Method to get saved onboarding data.
1315
- *
1316
  * @since 4.6.0
1317
  */
1318
  public function get_onboarding_data() {
1319
-
1320
  $onboarding_data = array();
1321
 
1322
  $onboarding_options = $this->get_onboarding_data_options();
1323
-
1324
  foreach ( $onboarding_options as $option ) {
1325
- $option_data = get_option( $option );
1326
- $onboarding_data[$option] = $option_data;
1327
  }
1328
 
1329
  return $onboarding_data;
@@ -1331,9 +1323,9 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1331
 
1332
  /**
1333
  * Method to get the current onboarding step
1334
- *
1335
  * @return int $onboarding_step Current onboarding step.
1336
- *
1337
  * @since 4.6.0
1338
  */
1339
  public static function get_onboarding_step() {
@@ -1343,9 +1335,9 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1343
 
1344
  /**
1345
  * Method to updatee the onboarding step
1346
- *
1347
- * @return bool
1348
- *
1349
  * @since 4.6.0
1350
  */
1351
  public static function update_onboarding_step( $step = 1 ) {
@@ -1353,34 +1345,34 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1353
  update_option( self::$onboarding_step_option, $step );
1354
  return true;
1355
  }
1356
-
1357
  return false;
1358
  }
1359
 
1360
  /**
1361
  * Method to check if onboarding is completed
1362
- *
1363
  * @return string
1364
- *
1365
  * @since 4.6.0
1366
  */
1367
  public static function is_onboarding_completed() {
1368
-
1369
  $onboarding_complete = get_option( 'ig_es_onboarding_complete', 'no' );
1370
 
1371
  if ( 'yes' === $onboarding_complete ) {
1372
  return true;
1373
  }
1374
 
1375
- return false;
1376
 
1377
  }
1378
 
1379
  /**
1380
  * Method to get next task for onboarding.
1381
- *
1382
  * @return string
1383
- *
1384
  * @since 4.6.0
1385
  */
1386
  public function get_next_onboarding_task() {
@@ -1399,7 +1391,7 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1399
  if ( ! empty( $current_task ) ) {
1400
  $current_task_index = array_search( $current_task, $onboarding_tasks, true );
1401
  if ( ! empty( $current_task_index ) ) {
1402
-
1403
  $next_task_index = $current_task_index + 1;
1404
  $next_task = ! empty( $onboarding_tasks[ $next_task_index ] ) ? $onboarding_tasks[ $next_task_index ] : '';
1405
 
@@ -1415,11 +1407,11 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1415
 
1416
  /**
1417
  * Method to check if all required task has been completed.
1418
- *
1419
  * @param string $task_name Task name.
1420
- *
1421
  * @return bool
1422
- *
1423
  * @since 4.6.0
1424
  */
1425
  public function is_required_tasks_completed( $task_name = '' ) {
@@ -1429,14 +1421,14 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1429
  }
1430
 
1431
  $required_tasks = $this->get_required_tasks( $task_name );
1432
-
1433
  // If there are not any required tasks which means this task can run without any dependency.
1434
  if ( empty( $required_tasks ) ) {
1435
  return true;
1436
  }
1437
-
1438
  $done_tasks = get_option( self::$onboarding_tasks_done_option, array() );
1439
-
1440
  // Variable to hold list of all done tasks without any grouping.
1441
  $all_done_tasks = array();
1442
  $is_required_tasks_done = false;
@@ -1454,13 +1446,13 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1454
  if ( empty( $remaining_required_tasks ) ) {
1455
  $is_required_tasks_done = true;
1456
  }
1457
-
1458
  return $is_required_tasks_done;
1459
  }
1460
 
1461
  /**
1462
  * Method to get lists of required tasks for this task.
1463
- *
1464
  * @return array $required_tasks List of required tasks.
1465
  */
1466
  public function get_required_tasks( $task_name = '' ) {
@@ -1473,8 +1465,8 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1473
  'check_test_email_on_server' => array(
1474
  'dispatch_emails_from_server',
1475
  ),
1476
- 'evaluate_email_delivery' => array(
1477
- 'check_test_email_on_server'
1478
  ),
1479
  );
1480
 
@@ -1483,6 +1475,6 @@ if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
1483
  return $required_tasks;
1484
  }
1485
  }
1486
-
1487
  IG_ES_Onboarding::instance();
1488
  }
16
 
17
 
18
  if ( ! class_exists( 'IG_ES_Onboarding' ) ) {
19
+
20
  /**
21
  * The onboarding-specific functionality of the plugin.
 
22
  */
23
  class IG_ES_Onboarding {
24
 
28
  * @var Onboarding instance
29
  */
30
  protected static $instance = null;
31
+
32
  /**
33
  * Added Logger Context
34
  *
35
  * @since 4.6.0
36
  * @var array
 
37
  */
38
  protected static $logger_context = array(
39
+ 'source' => 'ig_es_onboarding',
40
  );
41
+
42
  /**
43
  * Variable to hold all onboarding tasks list
44
  *
45
  * @since 4.6.0
46
  * @var array
 
47
  */
48
  private static $all_onboarding_tasks = array(
49
+ 'configuration_tasks' => array(
50
  'set_settings',
51
  'create_default_lists',
52
  'create_contacts_and_add_to_list',
62
  'check_test_email_on_server',
63
  'evaluate_email_delivery',
64
  ),
65
+ 'completion_tasks' => array(
66
  'subscribe_to_es',
67
  'save_final_configuration',
68
+ ),
69
  );
70
 
71
  /**
72
  * Option name for current task name.
73
+ *
74
  * @since 4.6.0
75
  * @var array
 
76
  */
77
  private static $onboarding_current_task_option = 'ig_es_onboarding_current_task';
78
 
79
  /**
80
  * Option name which holds common data between tasks.
81
+ *
82
  * E.g. created subscription form id from create_default_subscription_form function so we can use it in add_widget_to_sidebar
83
  *
84
  * @since 4.6.0
85
  * @var array
 
86
  */
87
  private static $onboarding_tasks_data_option = 'ig_es_onboarding_tasks_data';
88
 
89
  /**
90
  * Option name which holds tasks which are done.
91
+ *
92
  * @since 4.6.0
93
  * @var array
 
94
  */
95
  private static $onboarding_tasks_done_option = 'ig_es_onboarding_tasks_done';
96
+
97
  /**
98
  * Option name which holds tasks which are failed.
99
+ *
100
  * @since 4.6.0
101
  * @var array
 
102
  */
103
  private static $onboarding_tasks_failed_option = 'ig_es_onboarding_tasks_failed';
104
 
105
  /**
106
  * Option name which holds tasks which are skipped due to dependency on other tasks.
107
+ *
108
  * @since 4.6.0
109
  * @var array
 
110
  */
111
  private static $onboarding_tasks_skipped_option = 'ig_es_onboarding_tasks_skipped';
112
 
113
  /**
114
  * Option name which store the step which has been completed.
115
+ *
116
  * @since 4.6.0
117
  * @var string
 
118
  */
119
  private static $onboarding_step_option = 'ig_es_onboarding_step';
120
+
121
  /**
122
  * Initialize the class and set its properties.
123
  *
127
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
128
  add_action( 'wp_ajax_ig_es_handle_request', array( $this, 'handle_request' ) );
129
  }
130
+
131
  /**
132
  * Get class instance.
133
+ *
134
  * @since 4.6.0
135
  */
136
  public static function instance() {
139
  }
140
  return self::$instance;
141
  }
142
+
143
  /**
144
  * Register the JavaScript for the onboarding process.
145
+ *
146
  * @since 4.6.0
147
  */
148
  public function enqueue_scripts() {
149
+
150
  if ( ! ES()->is_es_admin_screen() ) {
151
  return;
152
  }
164
  }
165
  }
166
  }
167
+
168
  /**
169
  * Method to perform configuration and list, ES form, campaigns creation related operations in the onboarding
170
+ *
171
  * @since 4.6.0
172
  */
173
  public function handle_request() {
174
+
175
  $response = array();
176
 
177
  check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' );
187
 
188
  wp_send_json( $response );
189
  }
190
+
191
  /**
192
  * Method to perform configuration and list, ES form, campaigns creation related operations in the onboarding
193
+ *
194
  * @since 4.6.0
195
  */
196
  public function ajax_perform_configuration_tasks() {
201
 
202
  /**
203
  * Method to perform email delivery tasks.
204
+ *
205
  * @since 4.6.0
206
  */
207
  public function ajax_queue_default_broadcast_newsletter() {
210
 
211
  /**
212
  * Method to perform email delivery tasks.
213
+ *
214
  * @since 4.6.0
215
  */
216
  public function ajax_dispatch_emails_from_server() {
219
 
220
  /**
221
  * Method to perform email delivery tasks.
222
+ *
223
  * @since 4.6.0
224
  */
225
  public function ajax_check_test_email_on_server() {
229
 
230
  /**
231
  * Method to perform email delivery tasks.
232
+ *
233
  * @since 4.6.0
234
  */
235
  public function ajax_checking_spam_score_delivery_metrics() {
238
 
239
  /**
240
  * Method to perform email delivery tasks.
241
+ *
242
  * @since 4.6.0
243
  */
244
  public function ajax_evaluate_email_delivery() {
245
  return $this->perform_onboarding_tasks( 'email_delivery_check_tasks', 'evaluate_email_delivery' );
246
  }
247
+
248
  /**
249
  * Method to perform email delivery tasks.
250
+ *
251
  * @since 4.6.0
252
  */
253
  public function ajax_finishing_onboarding() {
257
  // Delete the onboarding data used during onboarding process.
258
  $this->delete_onboarding_data();
259
 
260
+ $dashboard_url = admin_url( 'admin.php?page=es_dashboard' );
261
  $response['redirect_url'] = $dashboard_url;
262
+
263
  return $response;
264
  }
265
 
266
  /**
267
  * Method to updatee the onboarding step
268
+ *
269
+ * @return bool
270
+ *
271
  * @since 4.6.0
272
  */
273
  public static function ajax_update_onboarding_step() {
287
 
288
  /**
289
  * Method to perform give onboarding tasks types.
290
+ *
291
  * @param string $task_group Tasks group
292
  * @param string $task_name Specific task
293
+ *
294
  * @since 4.6.0
295
  */
296
  public function perform_onboarding_tasks( $task_group = '', $task_name = '' ) {
319
  }
320
 
321
  $onboarding_tasks_done = get_option( self::$onboarding_tasks_done_option, array() );
322
+ $current_tasks_done = ! empty( $onboarding_tasks_done[ $task_group ] ) ? $onboarding_tasks_done[ $task_group ] : array();
323
+
324
  $onboarding_tasks_failed = get_option( self::$onboarding_tasks_failed_option, array() );
325
+ $current_tasks_failed = ! empty( $onboarding_tasks_failed[ $task_group ] ) ? $onboarding_tasks_failed[ $task_group ] : array();
326
 
327
  $onboarding_tasks_skipped = get_option( self::$onboarding_tasks_skipped_option, array() );
328
+ $current_tasks_skipped = ! empty( $onboarding_tasks_skipped[ $task_group ] ) ? $onboarding_tasks_skipped[ $task_group ] : array();
329
 
330
  $onboarding_tasks_data = get_option( self::$onboarding_tasks_data_option, array() );
331
  if ( ! empty( $current_tasks ) ) {
339
  $task_response = call_user_func( array( $this, $current_task ) );
340
  if ( 'success' === $task_response['status'] ) {
341
  if ( ! empty( $task_response['tasks_data'] ) ) {
342
+ if ( ! isset( $onboarding_tasks_data[ $current_task ] ) ) {
343
+ $onboarding_tasks_data[ $current_task ] = array();
344
  }
345
+ $onboarding_tasks_data[ $current_task ] = array_merge( $onboarding_tasks_data[ $current_task ], $task_response['tasks_data'] );
346
  }
347
  $logger->info( 'Task Done:' . $current_task, self::$logger_context );
348
  // Set success status only if not already set else it can override error/skipped statuses set previously from other tasks.
351
  }
352
  $current_tasks_done[] = $current_task;
353
  } elseif ( 'skipped' === $task_response['status'] ) {
354
+ $response['status'] = 'skipped';
355
  $current_tasks_skipped[] = $current_task;
356
  } else {
357
  $logger->info( 'Task Failed:' . $current_task, self::$logger_context );
358
+ $response['status'] = 'error';
359
  $current_tasks_failed[] = $current_task;
360
  }
 
 
361
 
362
+ $response['tasks'][ $current_task ] = $task_response;
363
+
364
+ $onboarding_tasks_done[ $task_group ] = $current_tasks_done;
365
+ $onboarding_tasks_failed[ $task_group ] = $current_tasks_failed;
366
+ $onboarding_tasks_skipped[ $task_group ] = $current_tasks_skipped;
367
 
368
  update_option( self::$onboarding_tasks_done_option, $onboarding_tasks_done );
369
  update_option( self::$onboarding_tasks_failed_option, $onboarding_tasks_failed );
374
  $logger->info( 'Missing Task:' . $current_task, self::$logger_context );
375
  }
376
  } else {
377
+ $response['tasks'][ $current_task ] = array(
378
  'status' => 'success',
379
  );
380
  $logger->info( 'Task already done:' . $current_task, self::$logger_context );
387
 
388
  /**
389
  * Set settings required for ES settings.
390
+ *
391
  * @since 4.6.0
392
  */
393
  public function set_settings() {
399
  $from_name = ig_es_get_request_data( 'es_from_name', '' );
400
  $from_email = ig_es_get_request_data( 'es_from_email', '' );
401
  $enable_double_optin = ig_es_get_request_data( 'enable_double_optin', 'yes' );
402
+ $optin_type = 'yes' === $enable_double_optin ? 'double_opt_in' : 'single_opt_in';
403
  $is_trial = ig_es_get_request_data( 'is_trial', '' );
404
  $allow_tracking = ig_es_get_request_data( 'allow_tracking', '' );
405
 
431
  * @since 4.0.0
432
  */
433
  public function create_default_lists() {
434
+
435
  $response = array(
436
  'status' => 'error',
437
  );
438
+
439
+ $default_list = ES()->lists_db->get_list_by_name( IG_DEFAULT_LIST );
440
  // Check if list already not exists.
441
  if ( empty( $default_list['id'] ) ) {
442
  // Add default list.
444
  } else {
445
  $default_list_id = $default_list['id'];
446
  }
447
+
448
  $main_list = ES()->lists_db->get_list_by_name( IG_MAIN_LIST );
449
  // Check if list already not exists.
450
  if ( empty( $main_list['id'] ) ) {
460
  } else {
461
  /* translators: 1. Main list name. 2. Default list name. */
462
  $response['message'] = sprintf( __( 'Unable to create %1$s and %2$s list.', 'email-subscribers' ), IG_MAIN_LIST, IG_DEFAULT_LIST );
463
+ $response['status'] = 'error';
464
  }
465
 
466
  return $response;
467
  }
468
+
469
  public function create_contacts_and_add_to_list() {
470
 
471
  // Flush cache to make sure we get data from DB instead of cache
507
  'status' => 'verified',
508
  'unsubscribed' => 0,
509
  'hash' => ES_Common::generate_guid(),
510
+ 'created_at' => ig_get_current_date_time(),
511
  );
512
 
513
  $contact_id = ES()->contacts_db->insert( $data );
514
  if ( $contact_id ) {
515
+
516
  // Prepare admin contact list data.
517
  $data = array(
518
  'contact_id' => $contact_id,
551
  'status' => 'verified',
552
  'unsubscribed' => 0,
553
  'hash' => ES_Common::generate_guid(),
554
+ 'created_at' => ig_get_current_date_time(),
555
  );
556
  $contact_id = ES()->contacts_db->insert( $data );
557
  if ( $contact_id ) {
562
  'subscribed_at' => ig_get_current_date_time(),
563
  'subscribed_ip' => null,
564
  );
565
+
566
  $contacts_added = ES()->lists_contacts_db->add_contact_to_lists( $data, $default_list_id );
567
  if ( $contacts_added ) {
568
  $response['status'] = 'success';
576
 
577
  /**
578
  * Add user registration workflow
579
+ *
580
  * @return $response
581
+ *
582
  * @since 4.6.0
583
  */
584
  public function add_workflow_for_user_registration() {
590
  $workflow_query_args = array(
591
  'trigger_name' => 'ig_es_user_registered',
592
  );
593
+
594
  $workflows = ES()->workflows_db->get_workflows( $workflow_query_args );
595
 
596
  // Add workflow only if there is no workflow for user registration already present.
606
  $workflow_meta = array();
607
  $workflow_meta['when_to_run'] = 'immediately';
608
  $workflow_status = 0;
609
+
610
  $workflow_actions = array(
611
  array(
612
  'action_name' => 'ig_es_add_to_list',
633
 
634
  return $response;
635
  }
636
+
637
  /**
638
  * Create default form
639
  *
649
  $default_list = ES()->lists_db->get_list_by_name( IG_MAIN_LIST );
650
  $list_id = $default_list['id'];
651
 
652
+ $body = array(
653
  array(
654
+ 'type' => 'text',
655
+ 'name' => 'Name',
656
+ 'id' => 'name',
657
+ 'params' => array(
658
  'label' => 'Name',
659
  'show' => true,
660
+ 'required' => true,
661
  ),
662
 
663
+ 'position' => 1,
664
  ),
665
 
666
  array(
667
+ 'type' => 'text',
668
+ 'name' => 'Email',
669
+ 'id' => 'email',
670
+ 'params' => array(
671
  'label' => 'Email',
672
  'show' => true,
673
+ 'required' => true,
674
  ),
675
 
676
+ 'position' => 2,
677
  ),
678
 
679
  array(
680
+ 'type' => 'checkbox',
681
+ 'name' => 'Lists',
682
+ 'id' => 'lists',
683
+ 'params' => array(
684
  'label' => 'Lists',
685
  'show' => false,
686
  'required' => true,
687
+ 'values' => array( $list_id ),
688
  ),
689
 
690
+ 'position' => 3,
691
  ),
692
 
693
  array(
694
+ 'type' => 'submit',
695
+ 'name' => 'submit',
696
+ 'id' => 'submit',
697
+ 'params' => array(
698
  'label' => 'Subscribe',
699
+ 'show' => true,
700
  ),
701
 
702
+ 'position' => 4,
703
  ),
704
 
705
  );
706
 
707
  $settings = array(
708
  'lists' => array( $list_id ),
709
+ 'desc' => '',
710
  );
711
+
712
  $add_gdpr_consent = ig_es_get_request_data( 'add_gdpr_consent', '' );
713
 
714
  // Add GDPR setting if admin has opted for.
729
  // Add Form.
730
  $form_id = ES()->forms_db->add_form( $form_data );
731
  if ( ! empty( $form_id ) ) {
732
+ $response['status'] = 'success';
733
  $response['tasks_data'] = array(
734
+ 'form_id' => $form_id,
735
  );
736
  } else {
737
  $response['status'] = 'error';
739
 
740
  return $response;
741
  }
742
+
743
  /**
744
  * Add ES widget to active sidebar
745
+ *
746
  * @since 4.6.0
747
  */
748
  public function add_widget_to_sidebar() {
760
  $onboarding_tasks_data = get_option( self::$onboarding_tasks_data_option, array() );
761
  // Get created form id from create_default_subscription_form task's data.
762
  if ( ! empty( $onboarding_tasks_data['create_default_subscription_form']['form_id'] ) ) {
763
+ $form_id = $onboarding_tasks_data['create_default_subscription_form']['form_id'];
764
+ $widget_data = array(
765
  'form_id' => $form_id,
766
  );
767
  $widget_added = ig_es_insert_widget_in_sidebar( 'email-subscribers-form', $widget_data, $sidebar_id );
768
  if ( $widget_added ) {
769
  $response['status'] = 'success';
770
  $response['tasks_data'] = array(
771
+ 'sidebar_id' => $sidebar_id,
772
  'sidebar_name' => $sidebar['name'],
773
  );
774
  /* translators: Active sidebar name. */
786
  }
787
  }
788
  }
789
+
790
  return $response;
791
  }
792
+
793
  /**
794
  * Create and send default broadcast while onboarding
795
  *
812
 
813
  // First Create Default Template.
814
  // Start-IG-Code.
815
+ $sample = '<strong style="color: #990000">What can you achieve using Email Subscribers?</strong><p>Add subscription forms on website, send HTML newsletters & automatically notify subscribers about new blog posts once it is published.';
816
  // End-IG-Code.
817
  // Start-Woo-Code.
818
+ $sample = '<strong style="color: #990000">What can you achieve using Email Subscribers?</strong><p>Add subscription forms on website, send HTML newsletters.';
819
  // End-Woo-Code.
820
  $sample .= ' You can also Import or Export subscribers from any list to Email Subscribers.</p>';
821
  $sample .= ' <strong style="color: #990000">Plugin Features</strong><ol>';
841
  'post_status' => 'publish',
842
  'post_type' => 'es_template',
843
  'meta_input' => array(
844
+ 'es_template_type' => 'newsletter',
845
+ ),
846
  );
847
 
848
  // Insert the post into the database
862
  $data['subject'] = $subject;
863
  $data['type'] = 'newsletter';
864
  $data['from_email'] = $from_email;
865
+ $data['reply_to_email'] = $from_email;
866
  $data['from_name'] = $from_name;
867
+ $data['reply_to_name'] = $from_name;
868
  $data['list_ids'] = $list_id;
869
  $data['base_template_id'] = $post_id;
870
  $data['body'] = $sample;
878
  'broadcast_id' => $broadcast_id,
879
  );
880
  }
 
881
  }
882
  }
883
 
886
 
887
  /**
888
  * Method to queue created default newsletter broadcast.
889
+ *
890
  * @since 4.6.0
891
+ */
892
  public function queue_default_broadcast_newsletter() {
893
 
894
  $response = array(
896
  );
897
 
898
  $onboarding_tasks_data = get_option( self::$onboarding_tasks_data_option, array() );
899
+ $campaign_id = ! empty( $onboarding_tasks_data['create_default_newsletter_broadcast']['broadcast_id'] ) ? $onboarding_tasks_data['create_default_newsletter_broadcast']['broadcast_id'] : 0;
900
+
901
  if ( ! empty( $campaign_id ) ) {
902
  $default_list = ES()->lists_db->get_list_by_name( IG_DEFAULT_LIST );
903
  if ( ! empty( $default_list ) ) {
905
  $subscribers = ES()->contacts_db->get_active_contacts_by_list_id( $list_id );
906
  if ( ! empty( $subscribers ) && count( $subscribers ) > 0 ) {
907
  $content_body = ES()->campaigns_db->get_column( 'body', $campaign_id );
908
+ $title = ES()->campaigns_db->get_column( 'name', $campaign_id );
909
  $guid = ES_Common::generate_guid( 6 );
910
  $now = ig_get_current_date_time();
911
 
921
  'created_at' => $now,
922
  'updated_at' => $now,
923
  );
924
+
925
  $report_id = ES_DB_Mailing_Queue::add_notification( $data );
926
+
927
  $delivery_data = array();
928
  $delivery_data['hash'] = $guid;
929
  $delivery_data['subscribers'] = $subscribers;
946
 
947
  /**
948
  * Method to send default broadcast campaign.
949
+ *
950
  * @since 4.6.0
951
  */
952
  public function dispatch_emails_from_server() {
957
 
958
  // Send test email to Icegram API only if trial is valid or user is premium user.
959
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
960
+
961
  $service = new ES_Send_Test_Email();
962
  $res = $service->send_test_email();
963
  }
964
 
965
  $onboarding_tasks_data = get_option( self::$onboarding_tasks_data_option, array() );
966
+ $campaign_id = ! empty( $onboarding_tasks_data['create_default_newsletter_broadcast']['broadcast_id'] ) ? $onboarding_tasks_data['create_default_newsletter_broadcast']['broadcast_id'] : 0;
967
  $report_id = ! empty( $onboarding_tasks_data['queue_default_broadcast_newsletter']['report_id'] ) ? $onboarding_tasks_data['queue_default_broadcast_newsletter']['report_id'] : 0;
968
+
969
  if ( ! empty( $campaign_id ) && ! empty( $report_id ) ) {
970
+
971
  $content_body = ES()->campaigns_db->get_column( 'body', $campaign_id );
972
  $title = ES()->campaigns_db->get_column( 'name', $campaign_id );
973
  $email_created = time();
1003
  update_option( 'ig_es_onboarding_test_campaign_success', 'yes' );
1004
  } else {
1005
  $response['status'] = 'error';
1006
+ $response['message'] = ! empty( $res['message'] ) ? $res['message'] : '';
1007
  $response['additional_message'] = __( 'Seems like your server is not setup correctly to send emails. Please confirm if you\'re getting any other emails from within WordPress', 'email-subscribers' );
1008
  update_option( 'ig_es_onboarding_test_campaign_error', 'yes' );
1009
  }
1015
 
1016
  /**
1017
  * Method to check test email on Icegram servers.
1018
+ *
1019
  * @since 4.6.0
1020
  */
1021
  public function check_test_email_on_server() {
1027
  // Check test email only if user has valid trial or is a premium user.
1028
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
1029
  $onboarding_tasks_failed = get_option( self::$onboarding_tasks_failed_option, array() );
1030
+ $email_delivery_check_tasks_failed = ! empty( $onboarding_tasks_failed['email_delivery_check_tasks'] ) ? $onboarding_tasks_failed['email_delivery_check_tasks'] : array();
1031
+
1032
  // Peform test email checking if dispatch_emails_from_server task hasn't failed.
1033
  if ( ! in_array( 'dispatch_emails_from_server', $email_delivery_check_tasks_failed, true ) ) {
1034
  $service = new ES_Email_Delivery_Check();
1043
 
1044
  /**
1045
  * Method to check spam score of test email recieved on Icegram servers.
1046
+ *
1047
  * @since 4.6.0
1048
  */
1049
  public function checking_spam_score_delivery_metrics() {
1055
  // Check spam score only if user has valid trial or is a premium user.
1056
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
1057
  $onboarding_tasks_failed = get_option( self::$onboarding_tasks_failed_option, array() );
1058
+ $email_delivery_check_tasks_failed = ! empty( $onboarding_tasks_failed['email_delivery_check_tasks'] ) ? $onboarding_tasks_failed['email_delivery_check_tasks'] : array();
1059
 
1060
  $onboarding_tasks_skipped = get_option( self::$onboarding_tasks_skipped_option, array() );
1061
+ $email_delivery_check_tasks_skipped = ! empty( $onboarding_tasks_skipped['email_delivery_check_tasks'] ) ? $onboarding_tasks_skipped['email_delivery_check_tasks'] : array();
1062
 
1063
  // Peform test email spam score only if check_test_email_on_server task hasn't failed or skipped.
1064
  if ( ! in_array( 'check_test_email_on_server', $email_delivery_check_tasks_failed, true ) && ! in_array( 'check_test_email_on_server', $email_delivery_check_tasks_skipped, true ) ) {
1073
 
1074
  /**
1075
  * Method to check test email on Icegram servers.
1076
+ *
1077
  * @since 4.6.0
1078
  */
1079
  public function evaluate_email_delivery() {
1085
  // Evaluate email delivery only if user has valid trial or is a premium user.
1086
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
1087
  $onboarding_tasks_failed = get_option( self::$onboarding_tasks_failed_option, array() );
1088
+ $email_delivery_check_tasks_failed = ! empty( $onboarding_tasks_failed['email_delivery_check_tasks'] ) ? $onboarding_tasks_failed['email_delivery_check_tasks'] : array();
1089
 
1090
  $onboarding_tasks_skipped = get_option( self::$onboarding_tasks_skipped_option, array() );
1091
+ $email_delivery_check_tasks_skipped = ! empty( $onboarding_tasks_skipped['email_delivery_check_tasks'] ) ? $onboarding_tasks_skipped['email_delivery_check_tasks'] : array();
1092
 
1093
  // Peform email delivery evaulation only if check_test_email_on_server task hasn't failed or skipped.
1094
  if ( ! in_array( 'check_test_email_on_server', $email_delivery_check_tasks_failed, true ) && ! in_array( 'check_test_email_on_server', $email_delivery_check_tasks_skipped, true ) ) {
1099
  }
1100
  return $response;
1101
  }
1102
+
1103
  /**
1104
  * Create default Post notification while on boarding
1105
  *
1108
  * @since 4.6.0
1109
  */
1110
  public function create_default_post_notification() {
1111
+
1112
+ $response = array(
1113
  'status' => 'error',
1114
  );
1115
  $create_post_notification = ig_es_get_request_data( 'create_post_notification', '' );
1138
  'post_status' => 'publish',
1139
  'post_type' => 'es_template',
1140
  'meta_input' => array(
1141
+ 'es_template_type' => 'post_notification',
1142
+ ),
1143
  );
1144
  // Insert the post into the database
1145
  $post_id = wp_insert_post( $post );
1149
  if ( ! empty( $post_id ) ) {
1150
  $list_id = $default_list['id'];
1151
 
1152
+ $categories_objects = get_terms(
1153
+ array(
1154
+ 'taxonomy' => 'category',
1155
+ 'hide_empty' => false,
1156
+ )
1157
+ );
1158
 
1159
  $categories = array();
1160
  if ( count( $categories_objects ) > 0 ) {
1181
 
1182
  $post_notification_id = ES()->campaigns_db->save_campaign( $data );
1183
  if ( $post_notification_id ) {
1184
+ $response['status'] = 'success';
1185
  $response['tasks_data'] = array(
1186
+ 'post_notification_id' => $post_notification_id,
1187
  );
1188
  }
1189
  }
1193
 
1194
  /**
1195
  * Method to subscribe to klawoo in the onboarding process.
1196
+ *
1197
  * @since 4.6.0
1198
+ */
1199
  public function subscribe_to_es() {
1200
 
1201
  $response = array(
1202
+ 'status' => 'error',
1203
  );
1204
 
1205
  $name = ig_es_get_request_data( 'name', '' );
1207
  $list = ig_es_get_request_data( 'list', '' );
1208
 
1209
  if ( ! empty( $list ) && is_email( $email ) ) {
1210
+
1211
  $url_params = array(
1212
  'ig_es_external_action' => 'subscribe',
1213
  'name' => $name,
1222
 
1223
  $ig_es_url = 'https://www.icegram.com/';
1224
  $ig_es_url = add_query_arg( $url_params, $ig_es_url );
1225
+
1226
  // Make a get request.
1227
  $api_response = wp_remote_get( $ig_es_url );
1228
  if ( ! is_wp_error( $api_response ) ) {
1241
 
1242
  /**
1243
  * Method to subscribe to klawoo in the onboarding process.
1244
+ *
1245
  * @since 4.6.0
1246
+ */
1247
  public function save_final_configuration() {
1248
 
1249
  $response = array();
1273
  );
1274
 
1275
  $onboarding_options = $this->get_onboarding_data_options();
1276
+
1277
  foreach ( $onboarding_options as $option ) {
1278
  $deleted = delete_option( $option );
1279
  }
1285
 
1286
  /**
1287
  * Method to get the onboarding data options used in onboarding process.
1288
+ *
1289
  * @since 4.6.0
1290
  */
1291
  public function get_onboarding_data_options() {
1304
 
1305
  /**
1306
  * Method to get saved onboarding data.
1307
+ *
1308
  * @since 4.6.0
1309
  */
1310
  public function get_onboarding_data() {
1311
+
1312
  $onboarding_data = array();
1313
 
1314
  $onboarding_options = $this->get_onboarding_data_options();
1315
+
1316
  foreach ( $onboarding_options as $option ) {
1317
+ $option_data = get_option( $option );
1318
+ $onboarding_data[ $option ] = $option_data;
1319
  }
1320
 
1321
  return $onboarding_data;
1323
 
1324
  /**
1325
  * Method to get the current onboarding step
1326
+ *
1327
  * @return int $onboarding_step Current onboarding step.
1328
+ *
1329
  * @since 4.6.0
1330
  */
1331
  public static function get_onboarding_step() {
1335
 
1336
  /**
1337
  * Method to updatee the onboarding step
1338
+ *
1339
+ * @return bool
1340
+ *
1341
  * @since 4.6.0
1342
  */
1343
  public static function update_onboarding_step( $step = 1 ) {
1345
  update_option( self::$onboarding_step_option, $step );
1346
  return true;
1347
  }
1348
+
1349
  return false;
1350
  }
1351
 
1352
  /**
1353
  * Method to check if onboarding is completed
1354
+ *
1355
  * @return string
1356
+ *
1357
  * @since 4.6.0
1358
  */
1359
  public static function is_onboarding_completed() {
1360
+
1361
  $onboarding_complete = get_option( 'ig_es_onboarding_complete', 'no' );
1362
 
1363
  if ( 'yes' === $onboarding_complete ) {
1364
  return true;
1365
  }
1366
 
1367
+ return false;
1368
 
1369
  }
1370
 
1371
  /**
1372
  * Method to get next task for onboarding.
1373
+ *
1374
  * @return string
1375
+ *
1376
  * @since 4.6.0
1377
  */
1378
  public function get_next_onboarding_task() {
1391
  if ( ! empty( $current_task ) ) {
1392
  $current_task_index = array_search( $current_task, $onboarding_tasks, true );
1393
  if ( ! empty( $current_task_index ) ) {
1394
+
1395
  $next_task_index = $current_task_index + 1;
1396
  $next_task = ! empty( $onboarding_tasks[ $next_task_index ] ) ? $onboarding_tasks[ $next_task_index ] : '';
1397
 
1407
 
1408
  /**
1409
  * Method to check if all required task has been completed.
1410
+ *
1411
  * @param string $task_name Task name.
1412
+ *
1413
  * @return bool
1414
+ *
1415
  * @since 4.6.0
1416
  */
1417
  public function is_required_tasks_completed( $task_name = '' ) {
1421
  }
1422
 
1423
  $required_tasks = $this->get_required_tasks( $task_name );
1424
+
1425
  // If there are not any required tasks which means this task can run without any dependency.
1426
  if ( empty( $required_tasks ) ) {
1427
  return true;
1428
  }
1429
+
1430
  $done_tasks = get_option( self::$onboarding_tasks_done_option, array() );
1431
+
1432
  // Variable to hold list of all done tasks without any grouping.
1433
  $all_done_tasks = array();
1434
  $is_required_tasks_done = false;
1446
  if ( empty( $remaining_required_tasks ) ) {
1447
  $is_required_tasks_done = true;
1448
  }
1449
+
1450
  return $is_required_tasks_done;
1451
  }
1452
 
1453
  /**
1454
  * Method to get lists of required tasks for this task.
1455
+ *
1456
  * @return array $required_tasks List of required tasks.
1457
  */
1458
  public function get_required_tasks( $task_name = '' ) {
1465
  'check_test_email_on_server' => array(
1466
  'dispatch_emails_from_server',
1467
  ),
1468
+ 'evaluate_email_delivery' => array(
1469
+ 'check_test_email_on_server',
1470
  ),
1471
  );
1472
 
1475
  return $required_tasks;
1476
  }
1477
  }
1478
+
1479
  IG_ES_Onboarding::instance();
1480
  }
lite/admin/partials/dashboard.php CHANGED
@@ -45,45 +45,45 @@ $settings_url = admin_url( 'admin.php?page=es_settings' );
45
  $facebook_url = 'https://www.facebook.com/groups/2298909487017349/';
46
 
47
  $feature_blocks = array(
48
- 'form' => array(
49
- 'title' => __('Add a Subscription Form', 'email-subscribers'),
50
- 'desc' => __('Grow subscribers. Add a newsletter signup form to your site.', 'email-subscribers'),
51
- 'cta_text' => __('Create', 'email-subscribers'),
52
- 'feature_url' => $new_form_url,
53
- 'graphics_img' => 'lite/admin/images/dashboard-subscriber-form.png',
54
- ),
55
-
56
- 'import_contacts' => array(
57
- 'title' => __('Import Contacts', 'email-subscribers'),
58
- 'desc' =>__('Coming from another email marketing system? Upload a CSV file to import subscribers.', 'email-subscribers'),
59
- 'cta_text' => __('Import', 'email-subscribers'),
60
- 'feature_url' => admin_url( 'admin.php?page=es_subscribers&action=import' ),
61
- 'graphics_img' => 'lite/admin/images/dashboard-import-contacts.png',
62
  ),
63
 
64
  'setup_email_sending' => array(
65
- 'title' => __('Configure Email Sending', 'email-subscribers'),
66
- 'desc' => __(' Essential for high email delivery and reaching the inbox. SMTP, email service providers... set it all up.', 'email-subscribers'),
67
- 'cta_text' => __('Setup', 'email-subscribers'),
68
- 'feature_url' => admin_url( 'admin.php?page=es_settings#tabs-email_sending' ),
69
- 'graphics_img' => 'lite/admin/images/dashboard-configure-email-sending.png',
70
  ),
71
 
72
- 'broadcast' => array(
73
- 'title' => __('Send a Newsletter', 'email-subscribers'),
74
- 'desc' => __('Broadcast a newsletter campaign to all or selected subscribers.', 'email-subscribers'),
75
- 'cta_text' => __('Begin', 'email-subscribers'),
76
- 'feature_url' => $new_broadcast_url,
77
- 'graphics_img' => 'lite/admin/images/dashboard-send-newsletter.png',
78
  ),
79
 
80
- 'autoresponder' => array(
81
- 'title' => __('Create an Auto-responder Sequence', 'email-subscribers'),
82
- 'desc' => __('Welcome emails, drip campaigns... Send automatic emails at regular intervals to engage readers.', 'email-subscribers'),
83
- 'cta_text' => __('Start', 'email-subscribers'),
84
- 'feature_url' => $new_sequence_url,
85
- 'graphics_img' => 'lite/admin/images/dashboard-autoresponder-sequence.png',
86
- 'documentation_url' => 'https://www.icegram.com/documentation/email-sequence/?utm_source=in_app&utm_medium=sequence&utm_campaign=es_doc_upsell',
87
  ),
88
  );
89
 
@@ -113,7 +113,7 @@ $topics_indexes = array_rand( $topics, 3 );
113
  <div>
114
  <span class="rounded-md shadow-sm">
115
  <button type="button" class="w-full ig-es-primary-button">
116
- <?php echo esc_html__( 'Create', 'email-subscribers' ); ?>
117
  <svg class="w-5 h-5 ml-2 -mr-1" fill="currentColor" viewBox="0 0 20 20">
118
  <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/>
119
  </svg>
@@ -128,12 +128,12 @@ $topics_indexes = array_rand( $topics, 3 );
128
  <!-- Start-IG-Code -->
129
  <a href="<?php echo esc_url( $new_post_notification_url ); ?>" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"><?php echo esc_html__( 'New Post Notification', 'email-subscribers' ); ?></a>
130
  <!-- End-IG-Code -->
131
- <?php if ( ES()->is_pro() ) { ?>
132
  <a href="<?php echo esc_url( $new_sequence_url ); ?>" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"><?php echo esc_html__( 'New Sequence', 'email-subscribers' ); ?></a>
133
- <?php } else { ?>
134
  <a href="<?php echo esc_url( $icegram_pricing_url ); ?>" target="_blank" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"><?php echo esc_html__( 'New Sequence', 'email-subscribers' ); ?>
135
  <span class="inline-flex px-2 text-xs font-semibold leading-5 text-green-800 bg-green-100 rounded-full"><?php echo esc_html__( 'Premium', 'email-subscribers' ); ?></span></a>
136
- <?php } ?>
137
  </div>
138
  <div class="border-t border-gray-100"></div>
139
  <div class="py-1">
@@ -214,9 +214,9 @@ $topics_indexes = array_rand( $topics, 3 );
214
 
215
  <div class="flex items-center px-2 py-2 md:justify-between">
216
  <div class="text-sm leading-5 text-gray-900">
217
- <?php
218
  echo wp_kses_post( $topics[ $index ]['title'] );
219
- if ( ! empty( $topics[ $index ]['label'] ) ) {
220
  ?>
221
  <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?php echo esc_attr( $topics[ $index ]['label_class'] ); ?>"><?php echo esc_html( $topics[ $index ]['label'] ); ?></span>
222
  <?php } ?>
@@ -268,7 +268,7 @@ $topics_indexes = array_rand( $topics, 3 );
268
  <?php echo esc_html( $data['desc'] ); ?>
269
  </p>
270
 
271
- <?php
272
  $feature_url = $data['feature_url'];
273
  if ( ! ES()->is_pro() && isset( $data['documentation_url'] ) ) {
274
  $feature_url = $data['documentation_url'];
@@ -280,7 +280,7 @@ $topics_indexes = array_rand( $topics, 3 );
280
  </a>
281
  </div>
282
  </div>
283
- <?php
284
  }
285
  ?>
286
  </div>
@@ -316,22 +316,22 @@ $topics_indexes = array_rand( $topics, 3 );
316
  });
317
 
318
  var labels =
319
- <?php
320
  if ( ! empty( $labels ) ) {
321
  echo json_encode( $labels );
322
  } else {
323
  echo "''";
324
- }
325
  ?>
326
  ;
327
 
328
  var values =
329
- <?php
330
  if ( ! empty( $values ) ) {
331
  echo json_encode( $values );
332
  } else {
333
  echo "''";
334
- }
335
  ?>
336
  ;
337
 
45
  $facebook_url = 'https://www.facebook.com/groups/2298909487017349/';
46
 
47
  $feature_blocks = array(
48
+ 'form' => array(
49
+ 'title' => __( 'Add a Subscription Form', 'email-subscribers' ),
50
+ 'desc' => __( 'Grow subscribers. Add a newsletter signup form to your site.', 'email-subscribers' ),
51
+ 'cta_text' => __( 'Create', 'email-subscribers' ),
52
+ 'feature_url' => $new_form_url,
53
+ 'graphics_img' => 'lite/admin/images/dashboard-subscriber-form.png',
54
+ ),
55
+
56
+ 'import_contacts' => array(
57
+ 'title' => __( 'Import Contacts', 'email-subscribers' ),
58
+ 'desc' => __( 'Coming from another email marketing system? Upload a CSV file to import subscribers.', 'email-subscribers' ),
59
+ 'cta_text' => __( 'Import', 'email-subscribers' ),
60
+ 'feature_url' => admin_url( 'admin.php?page=es_subscribers&action=import' ),
61
+ 'graphics_img' => 'lite/admin/images/dashboard-import-contacts.png',
62
  ),
63
 
64
  'setup_email_sending' => array(
65
+ 'title' => __( 'Configure Email Sending', 'email-subscribers' ),
66
+ 'desc' => __( ' Essential for high email delivery and reaching the inbox. SMTP, email service providers... set it all up.', 'email-subscribers' ),
67
+ 'cta_text' => __( 'Setup', 'email-subscribers' ),
68
+ 'feature_url' => admin_url( 'admin.php?page=es_settings#tabs-email_sending' ),
69
+ 'graphics_img' => 'lite/admin/images/dashboard-configure-email-sending.png',
70
  ),
71
 
72
+ 'broadcast' => array(
73
+ 'title' => __( 'Send a Newsletter', 'email-subscribers' ),
74
+ 'desc' => __( 'Broadcast a newsletter campaign to all or selected subscribers.', 'email-subscribers' ),
75
+ 'cta_text' => __( 'Begin', 'email-subscribers' ),
76
+ 'feature_url' => $new_broadcast_url,
77
+ 'graphics_img' => 'lite/admin/images/dashboard-send-newsletter.png',
78
  ),
79
 
80
+ 'autoresponder' => array(
81
+ 'title' => __( 'Create an Auto-responder Sequence', 'email-subscribers' ),
82
+ 'desc' => __( 'Welcome emails, drip campaigns... Send automatic emails at regular intervals to engage readers.', 'email-subscribers' ),
83
+ 'cta_text' => __( 'Start', 'email-subscribers' ),
84
+ 'feature_url' => $new_sequence_url,
85
+ 'graphics_img' => 'lite/admin/images/dashboard-autoresponder-sequence.png',
86
+ 'documentation_url' => 'https://www.icegram.com/documentation/email-sequence/?utm_source=in_app&utm_medium=sequence&utm_campaign=es_doc_upsell',
87
  ),
88
  );
89
 
113
  <div>
114
  <span class="rounded-md shadow-sm">
115
  <button type="button" class="w-full ig-es-primary-button">
116
+ <?php echo esc_html__( 'Create', 'email-subscribers' ); ?>
117
  <svg class="w-5 h-5 ml-2 -mr-1" fill="currentColor" viewBox="0 0 20 20">
118
  <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/>
119
  </svg>
128
  <!-- Start-IG-Code -->
129
  <a href="<?php echo esc_url( $new_post_notification_url ); ?>" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"><?php echo esc_html__( 'New Post Notification', 'email-subscribers' ); ?></a>
130
  <!-- End-IG-Code -->
131
+ <?php if ( ES()->is_pro() ) { ?>
132
  <a href="<?php echo esc_url( $new_sequence_url ); ?>" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"><?php echo esc_html__( 'New Sequence', 'email-subscribers' ); ?></a>
133
+ <?php } else { ?>
134
  <a href="<?php echo esc_url( $icegram_pricing_url ); ?>" target="_blank" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"><?php echo esc_html__( 'New Sequence', 'email-subscribers' ); ?>
135
  <span class="inline-flex px-2 text-xs font-semibold leading-5 text-green-800 bg-green-100 rounded-full"><?php echo esc_html__( 'Premium', 'email-subscribers' ); ?></span></a>
136
+ <?php } ?>
137
  </div>
138
  <div class="border-t border-gray-100"></div>
139
  <div class="py-1">
214
 
215
  <div class="flex items-center px-2 py-2 md:justify-between">
216
  <div class="text-sm leading-5 text-gray-900">
217
+ <?php
218
  echo wp_kses_post( $topics[ $index ]['title'] );
219
+ if ( ! empty( $topics[ $index ]['label'] ) ) {
220
  ?>
221
  <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?php echo esc_attr( $topics[ $index ]['label_class'] ); ?>"><?php echo esc_html( $topics[ $index ]['label'] ); ?></span>
222
  <?php } ?>
268
  <?php echo esc_html( $data['desc'] ); ?>
269
  </p>
270
 
271
+ <?php
272
  $feature_url = $data['feature_url'];
273
  if ( ! ES()->is_pro() && isset( $data['documentation_url'] ) ) {
274
  $feature_url = $data['documentation_url'];
280
  </a>
281
  </div>
282
  </div>
283
+ <?php
284
  }
285
  ?>
286
  </div>
316
  });
317
 
318
  var labels =
319
+ <?php
320
  if ( ! empty( $labels ) ) {
321
  echo json_encode( $labels );
322
  } else {
323
  echo "''";
324
+ }
325
  ?>
326
  ;
327
 
328
  var values =
329
+ <?php
330
  if ( ! empty( $values ) ) {
331
  echo json_encode( $values );
332
  } else {
333
  echo "''";
334
+ }
335
  ?>
336
  ;
337
 
lite/admin/partials/help.php CHANGED
@@ -66,13 +66,41 @@ $topics = ES_Common::get_useful_articles();
66
  $topics_indexes = array_rand( $topics, 5 );
67
 
68
  $articles = array(
69
- array( 'title' => 'Create and Send Newsletter Emails', 'link' => 'https://www.icegram.com/documentation/es-how-to-create-and-send-newsletter-emails/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page', 'class' => 'font-medium text-blue-500 hover:text-blue-700' ),
70
- array( 'title' => 'Schedule Cron Emails in cPanel', 'link' => 'https://www.icegram.com/documentation/es-how-to-schedule-cron-emails/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page', 'class' => 'font-medium text-blue-500 hover:text-blue-700' ),
71
- array( 'title' => 'How to enable consent checkbox in the subscribe form?', 'link' => 'https://www.icegram.com/documentation/es-gdpr-how-to-enable-consent-checkbox-in-the-subscription-form/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page', 'class' => 'font-medium text-blue-500 hover:text-blue-700' ),
72
- array( 'title' => 'What data Email Subscribers stores on your end?', 'link' => 'https://www.icegram.com/documentation/es-gdpr-what-data-email-subscribers-stores-on-your-end/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page', 'class' => 'font-medium text-blue-500 hover:text-blue-700' ),
73
- array( 'title' => 'Create and Send Post Notification Emails when new posts are published', 'link' => 'https://www.icegram.com/documentation/es-how-to-create-and-send-post-notification-emails-when-new-posts-are-published/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page', 'class' => 'font-medium text-blue-500 hover:text-blue-700' ),
74
- array( 'title' => 'Keywords in the Broadcast', 'link' => 'https://www.icegram.com/documentation/es-what-are-the-available-keywords-in-the-newsletters/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page', 'class' => 'font-medium text-blue-500 hover:text-blue-700' ),
75
- array( 'title' => 'Keywords in the Post Notifications', 'link' => 'https://www.icegram.com/documentation/es-what-are-the-available-keywords-in-the-post-notifications/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page', 'class' => 'font-medium text-blue-500 hover:text-blue-700' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  );
77
 
78
  ?>
@@ -120,8 +148,8 @@ $articles = array(
120
  <span class="rounded-md shadow-sm">
121
  <a href="<?php echo esc_url( $update_url ); ?>">
122
  <button type="button" class="inline-flex justify-center w-full px-4 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-white bg-indigo-600 border border-transparent rounded-md hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue">
123
- <?php
124
- echo esc_html__( 'Run the updater', 'email-subscribers' );
125
  ?>
126
  </button>
127
  </a>
@@ -138,8 +166,8 @@ $articles = array(
138
  <div class="flex w-2/3 py-2 justify-center <?php echo esc_attr( $contact_us_btn_class ); ?>">
139
  <span class="rounded-md shadow-sm">
140
  <button type="button" class="inline-flex justify-center w-full px-4 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-white bg-indigo-600 border border-transparent rounded-md hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue">
141
- <?php
142
- echo esc_html__( 'Contact US', 'email-subscribers' );
143
  ?>
144
  </button>
145
  </span>
@@ -155,9 +183,9 @@ $articles = array(
155
 
156
  <div class="flex items-center px-2 py-2 md:justify-between sm:px-2">
157
  <div class="text-sm leading-5 text-gray-900">
158
- <?php
159
  echo wp_kses_post( $topics[ $index ]['title'] );
160
- if ( ! empty( $topics[ $index ]['label'] ) ) {
161
  ?>
162
  <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?php echo esc_attr( $topics[ $index ]['label_class'] ); ?>"><?php echo esc_html( $topics[ $index ]['label'] ); ?></span>
163
  <?php } ?>
@@ -219,17 +247,17 @@ $articles = array(
219
  <span class="rounded-md shadow-sm">
220
  <?php if ( ! in_array( $ig_plugin['name'], $active_plugins ) ) { ?>
221
  <a href="<?php echo esc_url( $ig_plugin['install_url'] ); ?>">
222
- <?php
223
  }
224
 
225
- if ( ! in_array( $ig_plugin['name'], $all_plugins ) ) {
226
  ?>
227
  <button type="button" class="inline-flex justify-center w-full px-4 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-white bg-green-600 border border-transparent rounded-md hover:bg-green-500 focus:outline-none focus:shadow-outline-blue">
228
  <?php echo esc_html__( 'Install', 'email-subscribers' ); ?> </button>
229
  <?php } elseif ( in_array( $ig_plugin['name'], $inactive_plugins ) ) { ?>
230
  <button type="button" class="inline-flex justify-center w-full px-4 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-white bg-indigo-600 border border-transparent rounded-md hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue">
231
  <?php echo esc_html__( 'Activate', 'email-subscribers' ); ?> </button>
232
- <?php } ?>
233
  </a>
234
  </span>
235
  </div>
66
  $topics_indexes = array_rand( $topics, 5 );
67
 
68
  $articles = array(
69
+ array(
70
+ 'title' => 'Create and Send Newsletter Emails',
71
+ 'link' => 'https://www.icegram.com/documentation/es-how-to-create-and-send-newsletter-emails/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page',
72
+ 'class' => 'font-medium text-blue-500 hover:text-blue-700',
73
+ ),
74
+ array(
75
+ 'title' => 'Schedule Cron Emails in cPanel',
76
+ 'link' => 'https://www.icegram.com/documentation/es-how-to-schedule-cron-emails/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page',
77
+ 'class' => 'font-medium text-blue-500 hover:text-blue-700',
78
+ ),
79
+ array(
80
+ 'title' => 'How to enable consent checkbox in the subscribe form?',
81
+ 'link' => 'https://www.icegram.com/documentation/es-gdpr-how-to-enable-consent-checkbox-in-the-subscription-form/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page',
82
+ 'class' => 'font-medium text-blue-500 hover:text-blue-700',
83
+ ),
84
+ array(
85
+ 'title' => 'What data Email Subscribers stores on your end?',
86
+ 'link' => 'https://www.icegram.com/documentation/es-gdpr-what-data-email-subscribers-stores-on-your-end/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page',
87
+ 'class' => 'font-medium text-blue-500 hover:text-blue-700',
88
+ ),
89
+ array(
90
+ 'title' => 'Create and Send Post Notification Emails when new posts are published',
91
+ 'link' => 'https://www.icegram.com/documentation/es-how-to-create-and-send-post-notification-emails-when-new-posts-are-published/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page',
92
+ 'class' => 'font-medium text-blue-500 hover:text-blue-700',
93
+ ),
94
+ array(
95
+ 'title' => 'Keywords in the Broadcast',
96
+ 'link' => 'https://www.icegram.com/documentation/es-what-are-the-available-keywords-in-the-newsletters/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page',
97
+ 'class' => 'font-medium text-blue-500 hover:text-blue-700',
98
+ ),
99
+ array(
100
+ 'title' => 'Keywords in the Post Notifications',
101
+ 'link' => 'https://www.icegram.com/documentation/es-what-are-the-available-keywords-in-the-post-notifications/?utm_source=es&utm_medium=in_app&utm_campaign=view_docs_help_page',
102
+ 'class' => 'font-medium text-blue-500 hover:text-blue-700',
103
+ ),
104
  );
105
 
106
  ?>
148
  <span class="rounded-md shadow-sm">
149
  <a href="<?php echo esc_url( $update_url ); ?>">
150
  <button type="button" class="inline-flex justify-center w-full px-4 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-white bg-indigo-600 border border-transparent rounded-md hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue">
151
+ <?php
152
+ echo esc_html__( 'Run the updater', 'email-subscribers' );
153
  ?>
154
  </button>
155
  </a>
166
  <div class="flex w-2/3 py-2 justify-center <?php echo esc_attr( $contact_us_btn_class ); ?>">
167
  <span class="rounded-md shadow-sm">
168
  <button type="button" class="inline-flex justify-center w-full px-4 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-white bg-indigo-600 border border-transparent rounded-md hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue">
169
+ <?php
170
+ echo esc_html__( 'Contact US', 'email-subscribers' );
171
  ?>
172
  </button>
173
  </span>
183
 
184
  <div class="flex items-center px-2 py-2 md:justify-between sm:px-2">
185
  <div class="text-sm leading-5 text-gray-900">
186
+ <?php
187
  echo wp_kses_post( $topics[ $index ]['title'] );
188
+ if ( ! empty( $topics[ $index ]['label'] ) ) {
189
  ?>
190
  <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?php echo esc_attr( $topics[ $index ]['label_class'] ); ?>"><?php echo esc_html( $topics[ $index ]['label'] ); ?></span>
191
  <?php } ?>
247
  <span class="rounded-md shadow-sm">
248
  <?php if ( ! in_array( $ig_plugin['name'], $active_plugins ) ) { ?>
249
  <a href="<?php echo esc_url( $ig_plugin['install_url'] ); ?>">
250
+ <?php
251
  }
252
 
253
+ if ( ! in_array( $ig_plugin['name'], $all_plugins ) ) {
254
  ?>
255
  <button type="button" class="inline-flex justify-center w-full px-4 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-white bg-green-600 border border-transparent rounded-md hover:bg-green-500 focus:outline-none focus:shadow-outline-blue">
256
  <?php echo esc_html__( 'Install', 'email-subscribers' ); ?> </button>
257
  <?php } elseif ( in_array( $ig_plugin['name'], $inactive_plugins ) ) { ?>
258
  <button type="button" class="inline-flex justify-center w-full px-4 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-white bg-indigo-600 border border-transparent rounded-md hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue">
259
  <?php echo esc_html__( 'Activate', 'email-subscribers' ); ?> </button>
260
+ <?php } ?>
261
  </a>
262
  </span>
263
  </div>
lite/admin/partials/onboarding.php CHANGED
@@ -35,30 +35,33 @@
35
 
36
  <div class="flex-1">
37
  <div class="p-4 md:px-8 md:py-5">
38
- <span class="text-xs text-gray-400"><?php echo esc_html__( 'STEP 1 of 3', 'email-subscribers'); ?> </span>
39
  <h3
40
  class="mb-1 text-2xl font-bold leading-snug text-gray-800 sm:text-3xl"
41
  >
42
- <?php echo esc_html__( 'Welcome!', 'email-subscribers'); ?>
43
  </h3>
44
  <form id="es-send-email-form">
45
  <div class="space-y-5 text-gray-800">
46
  <p class="text-base -mb-2">
47
- <?php
48
- echo esc_html__( 'We\'ve simplified and automated email marketing, so you can get
49
- results quickly.', 'email-subscribers');
 
 
 
50
  ?>
51
  </p>
52
 
53
  <div class="space-y-1">
54
- <h3 class="text-base font-medium text-gray-900"><?php echo esc_html__( 'Essentials:', 'email-subscribers'); ?></h3>
55
 
56
  <div
57
  class="space-y-2 text-sm sm:space-y-0 sm:space-x-4 sm:flex sm:items-center"
58
  >
59
 
60
  <div class="w-full sm:w-1/2">
61
- <label for="es_from_name"><?php echo esc_html__( '"From" name for emails: ', 'email-subscribers'); ?></label>
62
  <input
63
  id="es_from_name" name="es_from_name" value="<?php echo esc_attr( $from_name ); ?>" required
64
  class="es_from_name block w-full mt-1 text-sm transition duration-150 ease-in-out rounded-md shadow-sm form-input sm:leading-5"
@@ -67,7 +70,7 @@
67
  </div>
68
 
69
  <div class="w-full sm:w-1/2">
70
- <label for="es_from_email"><?php echo esc_html__( '"From" email: ', 'email-subscribers'); ?></label>
71
  <input type="email"
72
  id="es_from_email" name="es_from_email" value="<?php echo esc_attr( $from_email ); ?>" required
73
  class="es_from_email es_onboard_email block w-full mt-1 text-sm transition duration-150 ease-in-out rounded-md shadow-sm form-input sm:leading-5"
@@ -78,13 +81,16 @@
78
  </div>
79
  <div class="">
80
  <h3 class="text-base font-medium text-gray-900">
81
- <?php echo esc_html__( 'Email delivery testing:', 'email-subscribers'); ?>
82
  </h3>
83
 
84
  <p class="text-sm leading-6 pt-1">
85
- <?php
86
- echo esc_html__( 'Add a couple of your own email addresses below. We will add
87
- them to your audience lists.', 'email-subscribers');
 
 
 
88
  ?>
89
  </p>
90
  <div
@@ -109,7 +115,7 @@
109
  </div>
110
 
111
  <div class="space-y-1 leading-5">
112
- <h3 class="text-base font-medium text-gray-900 -mb-0.5"><?php echo esc_html__( 'Your preferences:', 'email-subscribers'); ?></h3>
113
  <!-- Start-IG-Code -->
114
  <?php if ( ! ES()->is_premium() ) { ?>
115
  <div class="flex pt-1">
@@ -125,7 +131,7 @@
125
  <label for="es_free_trial_preference" class="text-sm">
126
  <?php
127
  /* translators: 1: Trial period in days. */
128
- echo esc_html__( sprintf( 'Enable %s days free trial of premium features - email delivery testing, automatic background sending, spam protection and more', ES()->trial->get_trial_period( 'in_days' ) ), 'email-subscribers' );
129
  ?>
130
  </label>
131
  </div>
@@ -163,9 +169,12 @@
163
  </div>
164
  <div class="pl-3">
165
  <label for="es_post_notification_preference" class="text-sm">
166
- <?php
167
- echo esc_html__( 'I want to send email notifications when new blog posts are
168
- published', 'email-subscribers');
 
 
 
169
  ?>
170
  </label>
171
  </div>
@@ -182,9 +191,12 @@
182
  </div>
183
  <div class="pl-3">
184
  <label for="ig_es_enable_double_optin" class="text-sm">
185
- <?php
186
- echo esc_html__( 'Enable double opt-in (people have to click a confirmation
187
- link in email before they\'re subscribed)', 'email-subscribers');
 
 
 
188
  ?>
189
  </label>
190
  </div>
@@ -199,7 +211,7 @@
199
  </div>
200
  <div class="pl-3">
201
  <label for="ig_es_add_gdpr_consent" class="text-sm">
202
- <?php echo esc_html__( 'Add GDPR consent in subscription forms', 'email-subscribers'); ?>
203
  </label>
204
  </div>
205
  </div>
@@ -212,7 +224,7 @@
212
  type="button" id="es-button-send"
213
  class="es-button-send relative inline-flex items-center px-4 py-2 text-base font-medium leading-5 text-white bg-indigo-800 border border-transparent rounded-md hover:bg-indigo-600 focus:outline-none focus:shadow-outline"
214
  >
215
- <?php echo esc_html__( 'Ok, set it up for me →', 'email-subscribers'); ?>
216
  </button>
217
  </div>
218
  </div>
@@ -242,17 +254,20 @@
242
 
243
  <div class="flex-1">
244
  <div style="height:33.2rem" class="p-4 md:px-8 md:py-5">
245
- <span class="text-xs text-gray-400"><?php echo esc_html__( 'STEP 2 of 3', 'email-subscribers'); ?> </span>
246
  <h3
247
  class="mb-2 text-2xl font-bold leading-snug text-gray-800 sm:text-3xl"
248
  >
249
- <?php echo esc_html__( 'Hold on, personalizing for you...', 'email-subscribers'); ?>
250
  </h3>
251
  <div class="space-y-4 text-gray-800">
252
  <p class="text-base">
253
- <?php
254
- echo esc_html__( 'We\'ll create audience lists, campaigns and a subscription form.
255
- And then try to send a test email to make sure everything works.', 'email-subscribers');
 
 
 
256
  ?>
257
  </p>
258
  <ul class="space-y-4 text-sm font-medium leading-5 text-gray-400">
@@ -262,9 +277,9 @@
262
  <span class="relative block w-2 h-2 bg-indigo-700 rounded-full"></span>
263
  </div>
264
  <p class="text-sm text-indigo-800">
265
- <?php
266
  /* translators: 1: Main List 2: Test List */
267
- echo sprintf( esc_html__('Creating audience lists - %1$s &amp; %2$s', 'email-subscribers'), esc_html( IG_MAIN_LIST ), esc_html( IG_DEFAULT_LIST ) );
268
  ?>
269
  </p>
270
  </li>
@@ -278,9 +293,9 @@
278
  ></span>
279
  </div>
280
  <p class="text-sm">
281
- <?php echo esc_html__('Subscribing you and ', 'email-subscribers'); ?>
282
  <span id="es_onboarding_emails_list"></span>
283
- <?php echo esc_html__(' to these lists', 'email-subscribers'); ?>
284
  </p>
285
  </li>
286
 
@@ -292,7 +307,7 @@
292
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
293
  ></span>
294
  </div>
295
- <p class="text-sm"><?php echo esc_html__('Creating a campaign - newsletter broadcast test', 'email-subscribers'); ?></p>
296
  </li>
297
 
298
  <!-- Start-IG-Code -->
@@ -304,7 +319,7 @@
304
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
305
  ></span>
306
  </div>
307
- <p class="text-sm"><?php echo esc_html__('Creating a campaign - new post notification test', 'email-subscribers'); ?></p>
308
  </li>
309
  <!-- End-IG-Code -->
310
 
@@ -316,7 +331,7 @@
316
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
317
  ></span>
318
  </div>
319
- <p class="text-sm"><?php echo esc_html__('Creating a subscription opt-in form for the Main list', 'email-subscribers'); ?></p>
320
  </li>
321
 
322
  <li id="ig-es-onboard-add_widget_to_sidebar" class="flex items-start space-x-3 group">
@@ -328,9 +343,12 @@
328
  ></span>
329
  </div>
330
  <p class="text-sm">
331
- <?php
332
- echo esc_html__('Adding the form to an active sidebar, so you can show it on
333
- the site', 'email-subscribers');
 
 
 
334
  ?>
335
  </p>
336
  </li>
@@ -344,7 +362,7 @@
344
  ></span>
345
  </div>
346
  <div>
347
- <p class="text-sm"><?php echo esc_html__('Testing email delivery...', 'email-subscribers'); ?></p>
348
  <ul class="mt-3 space-y-2 font-normal sm:space-y-3" id="ig-es-onboard-test-email-delivery-tasks-list">
349
  <li id="ig-es-onboard-queue_default_broadcast_newsletter" class="flex items-start space-x-3 group">
350
  <div
@@ -354,7 +372,7 @@
354
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
355
  ></span>
356
  </div>
357
- <p class="text-sm"><?php echo esc_html__('Queuing up campaign - newsletter broadcast test', 'email-subscribers'); ?></p>
358
  </li>
359
  <li id="ig-es-onboard-dispatch_emails_from_server" class="flex items-start space-x-3 group">
360
  <div
@@ -364,7 +382,7 @@
364
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
365
  ></span>
366
  </div>
367
- <p class="text-sm"><?php echo esc_html__('Dispatching emails from your server', 'email-subscribers'); ?></p>
368
  </li>
369
  <li id="ig-es-onboard-check_test_email_on_server" class="flex items-start space-x-3 group">
370
  <div
@@ -375,7 +393,7 @@
375
  ></span>
376
  </div>
377
  <p class="text-sm">
378
- <?php echo esc_html__('Waiting for test email to arrive on destination server', 'email-subscribers'); ?>
379
  </p>
380
  </li>
381
  <li id="ig-es-onboard-evaluate_email_delivery" class="flex items-start space-x-3 group">
@@ -386,7 +404,7 @@
386
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
387
  ></span>
388
  </div>
389
- <p class="text-sm"><?php echo esc_html__('Excellent! Email delivery setup is working well!', 'email-subscribers'); ?></p>
390
  </li>
391
  </ul>
392
  </div>
@@ -401,7 +419,7 @@
401
  class="relative inline-flex items-center px-4 py-2 text-base font-medium leading-5 text-white bg-indigo-800 border border-transparent rounded-md hover:bg-indigo-600 focus:outline-none focus:shadow-outline"
402
  data-error-text="<?php echo esc_attr__( 'Continue anyway →', 'email-subscribers' ); ?>"
403
  >
404
- <?php echo esc_html__('All good, let\'s finish up →', 'email-subscribers'); ?>
405
  </button>
406
  </div>
407
  </div>
@@ -436,28 +454,31 @@
436
  <div class="flex-1">
437
  <form id="ig-es-onboarding-final-steps-form">
438
  <div style="height:33.2rem" class="p-4 md:px-8 md:py-5">
439
- <span class="text-xs text-gray-400"><?php echo esc_html__('STEP 3 of 3', 'email-subscribers'); ?> </span>
440
  <h3
441
  class="mb-2 text-2xl font-bold leading-snug text-gray-800 sm:text-3xl"
442
  >
443
- <?php echo esc_html__('Done! Now speed up your success!', 'email-subscribers'); ?>
444
  </h3>
445
  <input type="hidden" id="sign-up-list" name="list" value="bc4f8995201a"/>
446
  <input type="hidden" id="sign-up-form-source" name="form-source" value=""/>
447
  <div class="space-y-3 text-gray-800">
448
 
449
  <div class="space-y-5 text-gray-800">
450
- <p class="text-base -mb-1"><?php echo esc_html__('Setup is complete. Couple of things to support you...', 'email-subscribers'); ?>
451
  </p>
452
  <!-- Start-IG-Code -->
453
  <div class="">
454
  <h3 class="text-base font-medium text-gray-900">
455
- <?php echo esc_html__('Free course: WordPress Email Marketing Masterclass 2021', 'email-subscribers'); ?>
456
  </h3>
457
  <p class="pt-2 text-sm leading-6">
458
- <?php
459
- echo esc_html__('How to build your list, make sure your email reach your
460
- audience and influence your audience.', 'email-subscribers');
 
 
 
461
  ?>
462
  </p>
463
  <div
@@ -482,19 +503,25 @@
482
  </div>
483
  </div>
484
 
485
- <?php if ( ! ES()->is_premium() ) { ?>
486
  <div id="es_free_trial_option">
487
  <h3 class="text-base font-medium text-gray-900 pt-2">
488
- <?php echo esc_html__('Premium features for free:', 'email-subscribers'); ?>
489
  </h3>
490
 
491
  <p class="text-sm leading-6 pt-1">
492
- <?php
493
  /* translators: 1: Trial period in days. */
494
- echo esc_html__( sprintf( 'Get %s days free trial of managed email sending, advance spam
 
 
495
  protection, security, email deliverability checks and more. No
496
  credit card required. Premium features will be disabled
497
- automatically after the trial if you don\'t continue.', ES()->trial->get_trial_period( 'in_days' ) ), 'email-subscribers' );
 
 
 
 
498
  ?>
499
  </p>
500
  <div class="flex my-2 sm:my-0 pt-1">
@@ -508,31 +535,31 @@
508
  </div>
509
  <div class="pl-3">
510
  <label for="es_free_pro_trial" class="text-sm">
511
- <?php echo esc_html__('Yes, start the trial', 'email-subscribers'); ?>
512
  </label>
513
  </div>
514
  </div>
515
  </div>
516
- <?php } ?>
517
  <!-- End-IG-Code -->
518
 
519
  <div class="space-y-1">
520
  <h3 class="text-base font-medium text-gray-900 pt-2">
521
- <?php echo esc_html__('Recommended next steps:', 'email-subscribers'); ?>
522
  </h3>
523
  <ul class="ml-4 space-y-2 text-sm list-disc pt-1.5">
524
- <li><?php echo esc_html__('Review "Settings" and make adjustments if needed', 'email-subscribers'); ?></li>
525
- <li><?php echo esc_html__('Import your contacts, create new campaigns and test', 'email-subscribers'); ?></li>
526
  <!-- Start-IG-Code -->
527
  <li>
528
- <?php echo esc_html__('Review', 'email-subscribers'); ?>
529
  <a
530
  class="text-indigo-800 hover:underline"
531
  href="https://www.icegram.com/knowledgebase_category/email-subscribers/"
532
  target="_blank"
533
- ><?php echo esc_html__('documentation', 'email-subscribers'); ?></a
534
  >
535
- <?php echo esc_html__('if you need any help', 'email-subscribers'); ?>
536
  </li>
537
  <!-- End-IG-Code -->
538
  </ul>
@@ -545,7 +572,7 @@
545
  <button
546
  type="button" id="ig-es-finish-onboarding-process"
547
  class="relative inline-flex items-center px-4 py-2 text-base font-medium leading-5 text-white bg-indigo-800 border border-transparent rounded-md hover:bg-indigo-600 focus:outline-none focus:shadow-outline">
548
- <span class="mr-1"><?php echo esc_html__('Complete setup &amp; take me to "Dashboard" ', 'email-subscribers'); ?></span>
549
  <span class="es-btn-arrow"> → </span>
550
  <svg style="display:none" class="es-btn-loader h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
551
  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
@@ -586,12 +613,12 @@
586
  </div>
587
  <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
588
  <h3 class="text-lg font-medium leading-6 text-gray-900" id="modal-headline">
589
- <?php echo esc_html__('Email sending did not work', 'email-subscribers'); ?>
590
  </h3>
591
  <div class="mt-2 space-y-4 leading-5 text-gray-800">
592
  <div>
593
  <p class="font-medium text-sm text-gray-900">
594
- <?php echo esc_html__('Here\'s the error we encountered:', 'email-subscribers'); ?>
595
  </p>
596
  <div class="bg-red-50 px-1 py-0.5 text-sm font-mono ig-es-onboarding-error">
597
  [error-message]
@@ -601,10 +628,13 @@
601
 
602
  </p>
603
  <p class="font-medium text-sm">
604
- <?php
605
- echo esc_html__('We recommend you solve this problem quickly after completing
 
606
  the setup. Do make sure emails are getting delivered before
607
- you send any real campaigns.', 'email-subscribers');
 
 
608
  ?>
609
  </p>
610
  </div>
@@ -618,7 +648,7 @@
618
  id="es-delivery-error-button"
619
  class="es-delivery-error-button relative inline-flex items-center px-4 py-2 text-base font-medium leading-5 text-white bg-indigo-800 border border-transparent rounded-md hover:bg-indigo-600 focus:outline-none focus:shadow-outline"
620
  >
621
- <?php echo esc_html__(' Understood, continue for now →', 'email-subscribers'); ?>
622
  </button>
623
  </span>
624
  </div>
35
 
36
  <div class="flex-1">
37
  <div class="p-4 md:px-8 md:py-5">
38
+ <span class="text-xs text-gray-400"><?php echo esc_html__( 'STEP 1 of 3', 'email-subscribers' ); ?> </span>
39
  <h3
40
  class="mb-1 text-2xl font-bold leading-snug text-gray-800 sm:text-3xl"
41
  >
42
+ <?php echo esc_html__( 'Welcome!', 'email-subscribers' ); ?>
43
  </h3>
44
  <form id="es-send-email-form">
45
  <div class="space-y-5 text-gray-800">
46
  <p class="text-base -mb-2">
47
+ <?php
48
+ echo esc_html__(
49
+ 'We\'ve simplified and automated email marketing, so you can get
50
+ results quickly.',
51
+ 'email-subscribers'
52
+ );
53
  ?>
54
  </p>
55
 
56
  <div class="space-y-1">
57
+ <h3 class="text-base font-medium text-gray-900"><?php echo esc_html__( 'Essentials:', 'email-subscribers' ); ?></h3>
58
 
59
  <div
60
  class="space-y-2 text-sm sm:space-y-0 sm:space-x-4 sm:flex sm:items-center"
61
  >
62
 
63
  <div class="w-full sm:w-1/2">
64
+ <label for="es_from_name"><?php echo esc_html__( '"From" name for emails: ', 'email-subscribers' ); ?></label>
65
  <input
66
  id="es_from_name" name="es_from_name" value="<?php echo esc_attr( $from_name ); ?>" required
67
  class="es_from_name block w-full mt-1 text-sm transition duration-150 ease-in-out rounded-md shadow-sm form-input sm:leading-5"
70
  </div>
71
 
72
  <div class="w-full sm:w-1/2">
73
+ <label for="es_from_email"><?php echo esc_html__( '"From" email: ', 'email-subscribers' ); ?></label>
74
  <input type="email"
75
  id="es_from_email" name="es_from_email" value="<?php echo esc_attr( $from_email ); ?>" required
76
  class="es_from_email es_onboard_email block w-full mt-1 text-sm transition duration-150 ease-in-out rounded-md shadow-sm form-input sm:leading-5"
81
  </div>
82
  <div class="">
83
  <h3 class="text-base font-medium text-gray-900">
84
+ <?php echo esc_html__( 'Email delivery testing:', 'email-subscribers' ); ?>
85
  </h3>
86
 
87
  <p class="text-sm leading-6 pt-1">
88
+ <?php
89
+ echo esc_html__(
90
+ 'Add a couple of your own email addresses below. We will add
91
+ them to your audience lists.',
92
+ 'email-subscribers'
93
+ );
94
  ?>
95
  </p>
96
  <div
115
  </div>
116
 
117
  <div class="space-y-1 leading-5">
118
+ <h3 class="text-base font-medium text-gray-900 -mb-0.5"><?php echo esc_html__( 'Your preferences:', 'email-subscribers' ); ?></h3>
119
  <!-- Start-IG-Code -->
120
  <?php if ( ! ES()->is_premium() ) { ?>
121
  <div class="flex pt-1">
131
  <label for="es_free_trial_preference" class="text-sm">
132
  <?php
133
  /* translators: 1: Trial period in days. */
134
+ echo esc_html__( sprintf( 'Enable %s days free trial of premium features - email delivery testing, automatic background sending, spam protection and more', ES()->trial->get_trial_period( 'in_days' ) ), 'email-subscribers' );
135
  ?>
136
  </label>
137
  </div>
169
  </div>
170
  <div class="pl-3">
171
  <label for="es_post_notification_preference" class="text-sm">
172
+ <?php
173
+ echo esc_html__(
174
+ 'I want to send email notifications when new blog posts are
175
+ published',
176
+ 'email-subscribers'
177
+ );
178
  ?>
179
  </label>
180
  </div>
191
  </div>
192
  <div class="pl-3">
193
  <label for="ig_es_enable_double_optin" class="text-sm">
194
+ <?php
195
+ echo esc_html__(
196
+ 'Enable double opt-in (people have to click a confirmation
197
+ link in email before they\'re subscribed)',
198
+ 'email-subscribers'
199
+ );
200
  ?>
201
  </label>
202
  </div>
211
  </div>
212
  <div class="pl-3">
213
  <label for="ig_es_add_gdpr_consent" class="text-sm">
214
+ <?php echo esc_html__( 'Add GDPR consent in subscription forms', 'email-subscribers' ); ?>
215
  </label>
216
  </div>
217
  </div>
224
  type="button" id="es-button-send"
225
  class="es-button-send relative inline-flex items-center px-4 py-2 text-base font-medium leading-5 text-white bg-indigo-800 border border-transparent rounded-md hover:bg-indigo-600 focus:outline-none focus:shadow-outline"
226
  >
227
+ <?php echo esc_html__( 'Ok, set it up for me →', 'email-subscribers' ); ?>
228
  </button>
229
  </div>
230
  </div>
254
 
255
  <div class="flex-1">
256
  <div style="height:33.2rem" class="p-4 md:px-8 md:py-5">
257
+ <span class="text-xs text-gray-400"><?php echo esc_html__( 'STEP 2 of 3', 'email-subscribers' ); ?> </span>
258
  <h3
259
  class="mb-2 text-2xl font-bold leading-snug text-gray-800 sm:text-3xl"
260
  >
261
+ <?php echo esc_html__( 'Hold on, personalizing for you...', 'email-subscribers' ); ?>
262
  </h3>
263
  <div class="space-y-4 text-gray-800">
264
  <p class="text-base">
265
+ <?php
266
+ echo esc_html__(
267
+ 'We\'ll create audience lists, campaigns and a subscription form.
268
+ And then try to send a test email to make sure everything works.',
269
+ 'email-subscribers'
270
+ );
271
  ?>
272
  </p>
273
  <ul class="space-y-4 text-sm font-medium leading-5 text-gray-400">
277
  <span class="relative block w-2 h-2 bg-indigo-700 rounded-full"></span>
278
  </div>
279
  <p class="text-sm text-indigo-800">
280
+ <?php
281
  /* translators: 1: Main List 2: Test List */
282
+ echo sprintf( esc_html__( 'Creating audience lists - %1$s &amp; %2$s', 'email-subscribers' ), esc_html( IG_MAIN_LIST ), esc_html( IG_DEFAULT_LIST ) );
283
  ?>
284
  </p>
285
  </li>
293
  ></span>
294
  </div>
295
  <p class="text-sm">
296
+ <?php echo esc_html__( 'Subscribing you and ', 'email-subscribers' ); ?>
297
  <span id="es_onboarding_emails_list"></span>
298
+ <?php echo esc_html__( ' to these lists', 'email-subscribers' ); ?>
299
  </p>
300
  </li>
301
 
307
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
308
  ></span>
309
  </div>
310
+ <p class="text-sm"><?php echo esc_html__( 'Creating a campaign - newsletter broadcast test', 'email-subscribers' ); ?></p>
311
  </li>
312
 
313
  <!-- Start-IG-Code -->
319
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
320
  ></span>
321
  </div>
322
+ <p class="text-sm"><?php echo esc_html__( 'Creating a campaign - new post notification test', 'email-subscribers' ); ?></p>
323
  </li>
324
  <!-- End-IG-Code -->
325
 
331
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
332
  ></span>
333
  </div>
334
+ <p class="text-sm"><?php echo esc_html__( 'Creating a subscription opt-in form for the Main list', 'email-subscribers' ); ?></p>
335
  </li>
336
 
337
  <li id="ig-es-onboard-add_widget_to_sidebar" class="flex items-start space-x-3 group">
343
  ></span>
344
  </div>
345
  <p class="text-sm">
346
+ <?php
347
+ echo esc_html__(
348
+ 'Adding the form to an active sidebar, so you can show it on
349
+ the site',
350
+ 'email-subscribers'
351
+ );
352
  ?>
353
  </p>
354
  </li>
362
  ></span>
363
  </div>
364
  <div>
365
+ <p class="text-sm"><?php echo esc_html__( 'Testing email delivery...', 'email-subscribers' ); ?></p>
366
  <ul class="mt-3 space-y-2 font-normal sm:space-y-3" id="ig-es-onboard-test-email-delivery-tasks-list">
367
  <li id="ig-es-onboard-queue_default_broadcast_newsletter" class="flex items-start space-x-3 group">
368
  <div
372
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
373
  ></span>
374
  </div>
375
+ <p class="text-sm"><?php echo esc_html__( 'Queuing up campaign - newsletter broadcast test', 'email-subscribers' ); ?></p>
376
  </li>
377
  <li id="ig-es-onboard-dispatch_emails_from_server" class="flex items-start space-x-3 group">
378
  <div
382
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
383
  ></span>
384
  </div>
385
+ <p class="text-sm"><?php echo esc_html__( 'Dispatching emails from your server', 'email-subscribers' ); ?></p>
386
  </li>
387
  <li id="ig-es-onboard-check_test_email_on_server" class="flex items-start space-x-3 group">
388
  <div
393
  ></span>
394
  </div>
395
  <p class="text-sm">
396
+ <?php echo esc_html__( 'Waiting for test email to arrive on destination server', 'email-subscribers' ); ?>
397
  </p>
398
  </li>
399
  <li id="ig-es-onboard-evaluate_email_delivery" class="flex items-start space-x-3 group">
404
  class="block w-2 h-2 transition duration-150 ease-in-out bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400"
405
  ></span>
406
  </div>
407
+ <p class="text-sm"><?php echo esc_html__( 'Excellent! Email delivery setup is working well!', 'email-subscribers' ); ?></p>
408
  </li>
409
  </ul>
410
  </div>
419
  class="relative inline-flex items-center px-4 py-2 text-base font-medium leading-5 text-white bg-indigo-800 border border-transparent rounded-md hover:bg-indigo-600 focus:outline-none focus:shadow-outline"
420
  data-error-text="<?php echo esc_attr__( 'Continue anyway →', 'email-subscribers' ); ?>"
421
  >
422
+ <?php echo esc_html__( 'All good, let\'s finish up →', 'email-subscribers' ); ?>
423
  </button>
424
  </div>
425
  </div>
454
  <div class="flex-1">
455
  <form id="ig-es-onboarding-final-steps-form">
456
  <div style="height:33.2rem" class="p-4 md:px-8 md:py-5">
457
+ <span class="text-xs text-gray-400"><?php echo esc_html__( 'STEP 3 of 3', 'email-subscribers' ); ?> </span>
458
  <h3
459
  class="mb-2 text-2xl font-bold leading-snug text-gray-800 sm:text-3xl"
460
  >
461
+ <?php echo esc_html__( 'Done! Now speed up your success!', 'email-subscribers' ); ?>
462
  </h3>
463
  <input type="hidden" id="sign-up-list" name="list" value="bc4f8995201a"/>
464
  <input type="hidden" id="sign-up-form-source" name="form-source" value=""/>
465
  <div class="space-y-3 text-gray-800">
466
 
467
  <div class="space-y-5 text-gray-800">
468
+ <p class="text-base -mb-1"><?php echo esc_html__( 'Setup is complete. Couple of things to support you...', 'email-subscribers' ); ?>
469
  </p>
470
  <!-- Start-IG-Code -->
471
  <div class="">
472
  <h3 class="text-base font-medium text-gray-900">
473
+ <?php echo esc_html__( 'Free course: WordPress Email Marketing Masterclass 2021', 'email-subscribers' ); ?>
474
  </h3>
475
  <p class="pt-2 text-sm leading-6">
476
+ <?php
477
+ echo esc_html__(
478
+ 'How to build your list, make sure your email reach your
479
+ audience and influence your audience.',
480
+ 'email-subscribers'
481
+ );
482
  ?>
483
  </p>
484
  <div
503
  </div>
504
  </div>
505
 
506
+ <?php if ( ! ES()->is_premium() ) { ?>
507
  <div id="es_free_trial_option">
508
  <h3 class="text-base font-medium text-gray-900 pt-2">
509
+ <?php echo esc_html__( 'Premium features for free:', 'email-subscribers' ); ?>
510
  </h3>
511
 
512
  <p class="text-sm leading-6 pt-1">
513
+ <?php
514
  /* translators: 1: Trial period in days. */
515
+ echo esc_html__(
516
+ sprintf(
517
+ 'Get %s days free trial of managed email sending, advance spam
518
  protection, security, email deliverability checks and more. No
519
  credit card required. Premium features will be disabled
520
+ automatically after the trial if you don\'t continue.',
521
+ ES()->trial->get_trial_period( 'in_days' )
522
+ ),
523
+ 'email-subscribers'
524
+ );
525
  ?>
526
  </p>
527
  <div class="flex my-2 sm:my-0 pt-1">
535
  </div>
536
  <div class="pl-3">
537
  <label for="es_free_pro_trial" class="text-sm">
538
+ <?php echo esc_html__( 'Yes, start the trial', 'email-subscribers' ); ?>
539
  </label>
540
  </div>
541
  </div>
542
  </div>
543
+ <?php } ?>
544
  <!-- End-IG-Code -->
545
 
546
  <div class="space-y-1">
547
  <h3 class="text-base font-medium text-gray-900 pt-2">
548
+ <?php echo esc_html__( 'Recommended next steps:', 'email-subscribers' ); ?>
549
  </h3>
550
  <ul class="ml-4 space-y-2 text-sm list-disc pt-1.5">
551
+ <li><?php echo esc_html__( 'Review "Settings" and make adjustments if needed', 'email-subscribers' ); ?></li>
552
+ <li><?php echo esc_html__( 'Import your contacts, create new campaigns and test', 'email-subscribers' ); ?></li>
553
  <!-- Start-IG-Code -->
554
  <li>
555
+ <?php echo esc_html__( 'Review', 'email-subscribers' ); ?>
556
  <a
557
  class="text-indigo-800 hover:underline"
558
  href="https://www.icegram.com/knowledgebase_category/email-subscribers/"
559
  target="_blank"
560
+ ><?php echo esc_html__( 'documentation', 'email-subscribers' ); ?></a
561
  >
562
+ <?php echo esc_html__( 'if you need any help', 'email-subscribers' ); ?>
563
  </li>
564
  <!-- End-IG-Code -->
565
  </ul>
572
  <button
573
  type="button" id="ig-es-finish-onboarding-process"
574
  class="relative inline-flex items-center px-4 py-2 text-base font-medium leading-5 text-white bg-indigo-800 border border-transparent rounded-md hover:bg-indigo-600 focus:outline-none focus:shadow-outline">
575
+ <span class="mr-1"><?php echo esc_html__( 'Complete setup &amp; take me to "Dashboard" ', 'email-subscribers' ); ?></span>
576
  <span class="es-btn-arrow"> → </span>
577
  <svg style="display:none" class="es-btn-loader h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
578
  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
613
  </div>
614
  <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
615
  <h3 class="text-lg font-medium leading-6 text-gray-900" id="modal-headline">
616
+ <?php echo esc_html__( 'Email sending did not work', 'email-subscribers' ); ?>
617
  </h3>
618
  <div class="mt-2 space-y-4 leading-5 text-gray-800">
619
  <div>
620
  <p class="font-medium text-sm text-gray-900">
621
+ <?php echo esc_html__( 'Here\'s the error we encountered:', 'email-subscribers' ); ?>
622
  </p>
623
  <div class="bg-red-50 px-1 py-0.5 text-sm font-mono ig-es-onboarding-error">
624
  [error-message]
628
 
629
  </p>
630
  <p class="font-medium text-sm">
631
+ <?php
632
+ echo esc_html__(
633
+ 'We recommend you solve this problem quickly after completing
634
  the setup. Do make sure emails are getting delivered before
635
+ you send any real campaigns.',
636
+ 'email-subscribers'
637
+ );
638
  ?>
639
  </p>
640
  </div>
648
  id="es-delivery-error-button"
649
  class="es-delivery-error-button relative inline-flex items-center px-4 py-2 text-base font-medium leading-5 text-white bg-indigo-800 border border-transparent rounded-md hover:bg-indigo-600 focus:outline-none focus:shadow-outline"
650
  >
651
+ <?php echo esc_html__( ' Understood, continue for now →', 'email-subscribers' ); ?>
652
  </button>
653
  </span>
654
  </div>
lite/includes/class-email-subscribers-activator.php CHANGED
@@ -41,7 +41,7 @@ class Email_Subscribers_Activator {
41
  *
42
  * @since 4.8.0
43
  */
44
- do_action('ig_es_plugin_activate');
45
  }
46
 
47
  public static function register_email_templates() {
@@ -60,7 +60,7 @@ class Email_Subscribers_Activator {
60
  'parent_item_colon' => '',
61
  'menu_name' => __( 'Email Subscribers', 'email-subscribers' ),
62
  'featured_image' => __( 'Thumbnail (For Visual Representation only)', 'email-subscribers' ),
63
- 'set_featured_image' => __( 'Set thumbnail', 'email-subscribers' )
64
  );
65
 
66
  $args = array(
@@ -76,7 +76,7 @@ class Email_Subscribers_Activator {
76
  'has_archive' => false,
77
  'hierarchical' => false,
78
  'menu_position' => null,
79
- 'supports' => array( 'title', 'editor', 'thumbnail' )
80
  );
81
 
82
  register_post_type( 'es_template', $args );
41
  *
42
  * @since 4.8.0
43
  */
44
+ do_action( 'ig_es_plugin_activate' );
45
  }
46
 
47
  public static function register_email_templates() {
60
  'parent_item_colon' => '',
61
  'menu_name' => __( 'Email Subscribers', 'email-subscribers' ),
62
  'featured_image' => __( 'Thumbnail (For Visual Representation only)', 'email-subscribers' ),
63
+ 'set_featured_image' => __( 'Set thumbnail', 'email-subscribers' ),
64
  );
65
 
66
  $args = array(
76
  'has_archive' => false,
77
  'hierarchical' => false,
78
  'menu_position' => null,
79
+ 'supports' => array( 'title', 'editor', 'thumbnail' ),
80
  );
81
 
82
  register_post_type( 'es_template', $args );
lite/includes/class-email-subscribers-deactivator.php CHANGED
@@ -40,7 +40,7 @@ class Email_Subscribers_Deactivator {
40
  *
41
  * @since 4.3.2
42
  */
43
- do_action('ig_es_plugin_deactivate');
44
  }
45
 
46
  }
40
  *
41
  * @since 4.3.2
42
  */
43
+ do_action( 'ig_es_plugin_deactivate' );
44
  }
45
 
46
  }
lite/includes/class-email-subscribers-i18n.php CHANGED
@@ -21,7 +21,9 @@ class Email_Subscribers_I18n {
21
 
22
  $plugin_text_domain = 'email-subscribers';
23
  load_plugin_textdomain(
24
- $plugin_text_domain, false, dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/'
 
 
25
  );
26
  }
27
 
21
 
22
  $plugin_text_domain = 'email-subscribers';
23
  load_plugin_textdomain(
24
+ $plugin_text_domain,
25
+ false,
26
+ dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/'
27
  );
28
  }
29
 
lite/includes/class-email-subscribers-loader.php CHANGED
@@ -58,11 +58,11 @@ class Email_Subscribers_Loader {
58
  * Add a new action to the collection to be registered with WordPress.
59
  *
60
  * @since 4.0
61
- * @param string $hook The name of the WordPress action that is being registered.
62
- * @param object $component A reference to the instance of the object on which the action is defined.
63
- * @param string $callback The name of the function definition on the $component.
64
- * @param int $priority Optional. The priority at which the function should be fired. Default is 10.
65
- * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1.
66
  */
67
  public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
68
  $this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args );
@@ -72,11 +72,11 @@ class Email_Subscribers_Loader {
72
  * Add a new filter to the collection to be registered with WordPress.
73
  *
74
  * @since 4.0
75
- * @param string $hook The name of the WordPress filter that is being registered.
76
- * @param object $component A reference to the instance of the object on which the filter is defined.
77
- * @param string $callback The name of the function definition on the $component.
78
- * @param int $priority Optional. The priority at which the function should be fired. Default is 10.
79
- * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1
80
  */
81
  public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
82
  $this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args );
@@ -87,12 +87,12 @@ class Email_Subscribers_Loader {
87
  * collection.
88
  *
89
  * @since 4.0
90
- * @param array $hooks The collection of hooks that is being registered (that is, actions or filters).
91
- * @param string $hook The name of the WordPress filter that is being registered.
92
- * @param object $component A reference to the instance of the object on which the filter is defined.
93
- * @param string $callback The name of the function definition on the $component.
94
- * @param int $priority The priority at which the function should be fired.
95
- * @param int $accepted_args The number of arguments that should be passed to the $callback.
96
  * @return array The collection of actions and filters registered with WordPress.
97
  */
98
  private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) {
@@ -102,7 +102,7 @@ class Email_Subscribers_Loader {
102
  'component' => $component,
103
  'callback' => $callback,
104
  'priority' => $priority,
105
- 'accepted_args' => $accepted_args
106
  );
107
 
108
  return $hooks;
58
  * Add a new action to the collection to be registered with WordPress.
59
  *
60
  * @since 4.0
61
+ * @param string $hook The name of the WordPress action that is being registered.
62
+ * @param object $component A reference to the instance of the object on which the action is defined.
63
+ * @param string $callback The name of the function definition on the $component.
64
+ * @param int $priority Optional. The priority at which the function should be fired. Default is 10.
65
+ * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1.
66
  */
67
  public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
68
  $this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args );
72
  * Add a new filter to the collection to be registered with WordPress.
73
  *
74
  * @since 4.0
75
+ * @param string $hook The name of the WordPress filter that is being registered.
76
+ * @param object $component A reference to the instance of the object on which the filter is defined.
77
+ * @param string $callback The name of the function definition on the $component.
78
+ * @param int $priority Optional. The priority at which the function should be fired. Default is 10.
79
+ * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1
80
  */
81
  public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
82
  $this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args );
87
  * collection.
88
  *
89
  * @since 4.0
90
+ * @param array $hooks The collection of hooks that is being registered (that is, actions or filters).
91
+ * @param string $hook The name of the WordPress filter that is being registered.
92
+ * @param object $component A reference to the instance of the object on which the filter is defined.
93
+ * @param string $callback The name of the function definition on the $component.
94
+ * @param int $priority The priority at which the function should be fired.
95
+ * @param int $accepted_args The number of arguments that should be passed to the $callback.
96
  * @return array The collection of actions and filters registered with WordPress.
97
  */
98
  private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) {
102
  'component' => $component,
103
  'callback' => $callback,
104
  'priority' => $priority,
105
+ 'accepted_args' => $accepted_args,
106
  );
107
 
108
  return $hooks;
lite/includes/class-email-subscribers-uninstall.php CHANGED
@@ -65,30 +65,30 @@ class Email_Subscribers_Uninstall {
65
  self::delete_all_es_tables();
66
 
67
  $sidebars_widgets = maybe_unserialize( get_option( 'sidebars_widgets', array() ) );
68
- $option_name = $wpdb->esc_like( 'ig_es_' ) . '%';
69
- $post_type = 'es_template';
70
 
71
- //Remove ES widgets from Sidebars
72
  foreach ( $sidebars_widgets as $sidebar_index => $sidebar ) {
73
  if ( is_array( $sidebar ) ) {
74
  foreach ( $sidebar as $index => $widget_id ) {
75
  if ( strpos( $widget_id, 'email-subscribers-form' ) !== false ) {
76
- unset( $sidebars_widgets[$sidebar_index][$index] );
77
  }
78
  }
79
- }
80
  }
81
-
82
  update_option( 'sidebars_widgets', $sidebars_widgets );
83
  delete_option( 'widget_email-subscribers-form' );
84
 
85
- //Delete postmeta data
86
  $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}postmeta where post_id IN ( SELECT ID from {$wpdb->prefix}posts where post_type = %s)", $post_type ) );
87
 
88
- //Delete all templates of ES
89
  $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}posts where post_type = %s", $post_type ) );
90
 
91
- //Delete all options from options table with prefix ig_es
92
  $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}options WHERE option_name LIKE %s", $option_name ) );
93
  }
94
 
65
  self::delete_all_es_tables();
66
 
67
  $sidebars_widgets = maybe_unserialize( get_option( 'sidebars_widgets', array() ) );
68
+ $option_name = $wpdb->esc_like( 'ig_es_' ) . '%';
69
+ $post_type = 'es_template';
70
 
71
+ // Remove ES widgets from Sidebars
72
  foreach ( $sidebars_widgets as $sidebar_index => $sidebar ) {
73
  if ( is_array( $sidebar ) ) {
74
  foreach ( $sidebar as $index => $widget_id ) {
75
  if ( strpos( $widget_id, 'email-subscribers-form' ) !== false ) {
76
+ unset( $sidebars_widgets[ $sidebar_index ][ $index ] );
77
  }
78
  }
79
+ }
80
  }
81
+
82
  update_option( 'sidebars_widgets', $sidebars_widgets );
83
  delete_option( 'widget_email-subscribers-form' );
84
 
85
+ // Delete postmeta data
86
  $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}postmeta where post_id IN ( SELECT ID from {$wpdb->prefix}posts where post_type = %s)", $post_type ) );
87
 
88
+ // Delete all templates of ES
89
  $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}posts where post_type = %s", $post_type ) );
90
 
91
+ // Delete all options from options table with prefix ig_es
92
  $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}options WHERE option_name LIKE %s", $option_name ) );
93
  }
94
 
lite/includes/class-email-subscribers.php CHANGED
@@ -39,7 +39,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
39
  * @since 4.2.1
40
  *
41
  * @var Email_Subscribers The one true Email_Subscribers
42
- *
43
  */
44
  private static $instance;
45
 
@@ -48,7 +47,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
48
  *
49
  * @since 4.2.1
50
  * @var object|ES_Queue
51
- *
52
  */
53
  public $queue;
54
 
@@ -57,7 +55,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
57
  *
58
  * @since 4.2.1
59
  * @var object|ES_DB_Queue
60
- *
61
  */
62
  public $queue_db;
63
  /**
@@ -65,7 +62,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
65
  *
66
  * @since 4.2.1
67
  * @var object|ES_Actions
68
- *
69
  */
70
  public $actions;
71
 
@@ -74,7 +70,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
74
  *
75
  * @since 4.3.1
76
  * @var object|ES_Cron
77
- *
78
  */
79
  public $cron;
80
 
@@ -83,7 +78,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
83
  *
84
  * @since 4.3.9
85
  * @var object|ES_Compatibility
86
- *
87
  */
88
  public $compatibiloty;
89
 
@@ -92,7 +86,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
92
  *
93
  * @since 4.2.1
94
  * @var object|ES_DB_Actions
95
- *
96
  */
97
  public $actions_db;
98
 
@@ -102,7 +95,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
102
  * @since 4.2.1
103
  *
104
  * @var $feedback
105
- *
106
  */
107
  public $feedback;
108
 
@@ -112,7 +104,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
112
  * @since 4.2.1
113
  *
114
  * @var $tracker
115
- *
116
  */
117
  public $tracker;
118
 
@@ -131,7 +122,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
131
  * @since 4.2.1
132
  *
133
  * @var object|ES_DB_Campaigns
134
- *
135
  */
136
  public $campaigns_db;
137
 
@@ -140,7 +130,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
140
  *
141
  * @since 4.2.1
142
  * @var object|ES_Lists_Table
143
- *
144
  */
145
  public $lists;
146
 
@@ -150,7 +139,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
150
  * @since 4.2.1
151
  *
152
  * @var object|ES_DB_Lists
153
- *
154
  */
155
  public $lists_db;
156
 
@@ -159,7 +147,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
159
  *
160
  * @since 4.2.1
161
  * @var object|ES_Forms_Table
162
- *
163
  */
164
  public $forms;
165
 
@@ -223,7 +210,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
223
  * @since 4.2.1
224
  *
225
  * @var object|ES_Integrations
226
- *
227
  */
228
  public $integrations;
229
 
@@ -233,7 +219,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
233
  * @since 4.2.1
234
  *
235
  * @var object|IG_Logger
236
- *
237
  */
238
  public $logger;
239
 
@@ -320,11 +305,11 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
320
  * @since 4.0.0
321
  */
322
  public function add_admin_notice() {
323
- ///Halloween offer
324
- $show_offer = false;
325
  $current_page = ig_es_get_request_data( 'page' );
326
-
327
- if ( $this->can_upsell_features( array( 'lite', 'trial', 'starter' ) ) && IG_ES_Onboarding::is_onboarding_completed() ) {
328
  if ( 'es_reports' === $current_page ) {
329
  $report_insight = ig_es_get_request_data( 'insight' );
330
  if ( ! $report_insight ) {
@@ -332,7 +317,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
332
  }
333
  } else {
334
  $show_offer = true;
335
- }
336
  }
337
 
338
  if ( $show_offer ) {
@@ -352,7 +337,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
352
  return;
353
  }
354
 
355
- //cron notice
356
  $notice_option = get_option( 'ig_es_wp_cron_notice' );
357
 
358
  $show_notice = true;
@@ -372,8 +357,10 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
372
  $disable_wp_cron_notice .= '<br/>' . sprintf( __( 'Or schedule Cron in <a href="%s" target="_blank">cPanel</a>', 'email-subscribers' ), $cpanel_url );
373
  /* translators: %s: ES Pro URL */
374
  $disable_wp_cron_notice .= '<br/>' . sprintf( __( 'Or use <strong><a href="%s" target="_blank">Email Subscribers Pro</a></strong> for automatic Cron support', 'email-subscribers' ), $es_pro_url );
375
- $html = '<div class="notice notice-warning" style="background-color: #FFF;"><p style="letter-spacing: 0.6px;">' . $disable_wp_cron_notice . '<a style="float:right" class="es-admin-btn es-admin-btn-secondary " href="' . admin_url() . '?es_dismiss_admin_notice=1&option_name=wp_cron_notice">' . __( 'OK, I Got it!',
376
- 'email-subscribers' ) . '</a></p></div>';
 
 
377
  $args['html'] = $html;
378
  ES_Admin_Notices::add_custom_notice( 'show_wp_cron', $args );
379
  } else {
@@ -563,7 +550,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
563
  define( 'IG_ES_MAX_EMAIL_SEND_AT_ONCE', 30 );
564
  }
565
 
566
-
567
  if ( ! defined( 'IG_ES_CAMPAIGN_STATUS_IN_ACTIVE' ) ) {
568
  define( 'IG_ES_CAMPAIGN_STATUS_IN_ACTIVE', 0 );
569
  }
@@ -604,7 +590,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
604
  define( 'IG_ES_MAILING_QUEUE_STATUS_SENT', 'Sent' );
605
  }
606
 
607
-
608
  if ( ! defined( 'IG_ES_WORKFLOW_STATUS_IN_ACTIVE' ) ) {
609
  define( 'IG_ES_WORKFLOW_STATUS_IN_ACTIVE', 0 );
610
  }
@@ -616,7 +601,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
616
  if ( ! defined( 'IG_ES_TRIAL_PERIOD_IN_DAYS' ) ) {
617
  define( 'IG_ES_TRIAL_PERIOD_IN_DAYS', 14 );
618
  }
619
-
620
  if ( ! defined( 'IG_ES_PRODUCT_ID' ) ) {
621
  define( 'IG_ES_PRODUCT_ID', 1002 );
622
  }
@@ -650,7 +635,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
650
  * with WordPress.
651
  *
652
  * @since 4.0
653
- *
654
  */
655
  private function load_dependencies() {
656
 
@@ -671,7 +655,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
671
  // Admin Notices
672
  'lite/includes/notices/class-es-admin-notices.php',
673
 
674
-
675
  // Database class files
676
  'lite/includes/db/class-es-db.php',
677
  'lite/includes/db/class-es-db-queue.php',
@@ -753,7 +736,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
753
  // Install/ Update
754
  'lite/includes/upgrade/es-update-functions.php',
755
  'lite/includes/class-es-install.php',
756
-
757
  // Onboarding process handler class.
758
  'lite/admin/class-ig-es-onboarding.php',
759
 
@@ -772,7 +755,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
772
  // Pro Feature
773
  'lite/includes/pro-features.php',
774
  // End-IG-Code.
775
-
776
  // Feedback Class
777
  'lite/includes/feedback/class-ig-tracker.php',
778
  // Start-IG-Code.
@@ -780,11 +763,11 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
780
  'lite/includes/feedback/class-ig-plugin-usage-tracker.php',
781
  'lite/includes/feedback.php',
782
  // End-IG-Code.
783
-
784
  // WC session tracking
785
  'lite/includes/classes/class-ig-es-wc-session-tracker.php',
786
  'lite/includes/classes/ig-es-wc-cookies.php',
787
-
788
  // Workflows
789
  'lite/includes/workflows/db/class-es-db-workflows.php',
790
  'lite/includes/workflows/db/class-es-db-workflows-queue.php',
@@ -795,7 +778,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
795
  'lite/includes/workflows/abstracts/class-es-workflow-action.php',
796
  'lite/includes/workflows/abstracts/class-es-workflow-data-type.php',
797
  'lite/includes/workflows/abstracts/class-ig-es-workflow-variable.php',
798
-
799
  // Workflow Utility
800
  'lite/includes/workflows/class-es-clean.php',
801
  'lite/includes/workflows/class-es-format.php',
@@ -810,18 +793,18 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
810
  // Workflow
811
  'lite/includes/workflows/class-es-workflow.php',
812
  'lite/includes/workflows/class-es-workflow-factory.php',
813
-
814
  // Data Types
815
  'lite/includes/workflows/data-types/abstracts/class-es-data-type-form-data.php',
816
  'lite/includes/workflows/data-types/class-es-data-type-user.php',
817
  'lite/includes/workflows/data-types/class-es-data-type-subscriber.php',
818
  'lite/includes/workflows/class-es-workflow-data-types.php',
819
-
820
  'lite/includes/workflows/variables/class-es-workflow-data-types.php',
821
-
822
  // Data Layer
823
  'lite/includes/workflows/class-es-workflow-data-layer.php',
824
-
825
  // Workflow Fields
826
  'lite/includes/workflows/fields/class-es-field.php',
827
  'lite/includes/workflows/fields/class-es-text.php',
@@ -831,22 +814,22 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
831
  'lite/includes/workflows/fields/class-es-select.php',
832
  'lite/includes/workflows/fields/class-es-checkbox.php',
833
  'lite/includes/workflows/fields/class-es-wp-editor.php',
834
-
835
  // Workflow Admin
836
  'lite/includes/workflows/admin/class-es-workflow-admin.php',
837
  'lite/includes/workflows/admin/class-es-workflow-admin-edit.php',
838
  'lite/includes/workflows/admin/class-es-workflow-admin-ajax.php',
839
-
840
  // Workflow Triggers.
841
  'lite/includes/workflows/triggers/abstracts/class-es-trigger-form-submitted.php',
842
  'lite/includes/workflows/triggers/class-es-trigger-user-registered.php',
843
  'lite/includes/workflows/triggers/class-es-trigger-user-deleted.php',
844
  'lite/includes/workflows/triggers/class-es-trigger-user-updated.php',
845
  'lite/includes/workflows/class-es-workflow-triggers.php',
846
-
847
  // Abstracts workflow actions
848
  'lite/includes/workflows/actions/abstracts/class-ig-es-action-send-email-abstract.php',
849
-
850
  // Workflow Actions.
851
  'lite/includes/workflows/actions/class-es-action-add-to-list.php',
852
  'lite/includes/workflows/actions/class-es-action-move-contact.php',
@@ -854,11 +837,11 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
854
  'lite/includes/workflows/actions/class-es-action-delete-contact.php',
855
  'lite/includes/workflows/actions/class-es-action-update-contact.php',
856
  'lite/includes/workflows/class-es-workflow-actions.php',
857
-
858
  // Workflow Query
859
  'lite/includes/workflows/class-es-workflow-query.php',
860
-
861
- // Workflow Queue
862
  'lite/includes/workflows/queue/class-es-workflow-queue.php',
863
  'lite/includes/workflows/queue/class-es-workflow-queue-factory.php',
864
  'lite/includes/workflows/queue/class-es-workflow-queue-handler.php',
@@ -869,13 +852,16 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
869
 
870
  // Premium services ui components.
871
  'lite/includes/premium-services-ui/class-ig-es-premium-services-ui.php',
872
-
873
  // Background Process Helper
874
  'lite/includes/classes/class-ig-es-background-process-helper.php',
875
-
876
  // Subscribers Query
877
  'lite/includes/classes/class-ig-es-subscriber-query.php',
878
-
 
 
 
879
  // Campaign Rules
880
  'lite/admin/class-ig-es-campaign-rules.php',
881
 
@@ -883,7 +869,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
883
  'pro/pro-class-email-subscribers.php',
884
 
885
  );
886
-
887
  foreach ( $files_to_load as $file ) {
888
  if ( is_file( ES_PLUGIN_DIR . $file ) ) {
889
  require_once ES_PLUGIN_DIR . $file;
@@ -915,7 +901,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
915
  * of the plugin.
916
  *
917
  * @since 4.0
918
- *
919
  */
920
  private function define_admin_hooks() {
921
 
@@ -940,7 +925,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
940
  * of the plugin.
941
  *
942
  * @since 4.0
943
- *
944
  */
945
  private function define_public_hooks() {
946
 
@@ -997,9 +981,9 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
997
 
998
  /**
999
  * Method to get if user has opted for trial or not.
1000
- *
1001
  * @return bool
1002
- *
1003
  * @since 4.6.0
1004
  */
1005
  public function is_trial() {
@@ -1024,9 +1008,9 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1024
 
1025
  /**
1026
  * Method to get if trial has expired or not.
1027
- *
1028
  * @return bool
1029
- *
1030
  * @since 4.6.1
1031
  */
1032
  public function is_trial_expired() {
@@ -1036,13 +1020,13 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1036
  if ( 'yes' === $is_trial ) {
1037
  $trial_started_at = get_option( 'ig_es_trial_started_at' );
1038
  if ( ! empty( $trial_started_at ) ) {
1039
-
1040
  // Get current timestamp.
1041
  $current_time = time();
1042
-
1043
  // Get the timestamp when trial will expire.
1044
  $trial_expires_at = $trial_started_at + ES()->trial->get_trial_period();
1045
-
1046
  // Check if current time is greater than expiry time.
1047
  if ( $current_time > $trial_expires_at ) {
1048
  $is_trial_expired = true;
@@ -1055,9 +1039,9 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1055
 
1056
  /**
1057
  * Method to check if trial is valid.
1058
- *
1059
  * @return bool $is_trial_valid Is trial valid
1060
- *
1061
  * @since 4.6.1
1062
  */
1063
  public function is_trial_valid() {
@@ -1068,20 +1052,20 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1068
 
1069
  /**
1070
  * Method to validate a premium service request
1071
- *
1072
  * @param array $service Request
1073
- *
1074
  * @return bool
1075
- *
1076
  * @since 4.6.1
1077
  */
1078
  public function validate_service_request( $services = array() ) {
1079
  $is_request_valid = false;
1080
-
1081
  // Check if trial is still valid.
1082
  if ( $this->is_trial_valid() ) {
1083
  $is_request_valid = true;
1084
- } else if ( $this->is_premium() ) {
1085
  $es_services = apply_filters( 'ig_es_services', array() );
1086
  if ( ! empty( $es_services ) ) {
1087
  // Check if there is not any invalid service in $services array which is not present in the $es_services.
@@ -1167,7 +1151,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1167
  */
1168
  public function can_upsell_features( $show_for_plans = array() ) {
1169
  $es_current_plan = $this->get_plan();
1170
- if ( in_array( $es_current_plan, $show_for_plans ) ) {
1171
  return true;
1172
  }
1173
  return false;
@@ -1204,7 +1188,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1204
  "{$prefix}_page_es_pricing",
1205
  "{$prefix}_page_es_sequence",
1206
 
1207
-
1208
  );
1209
 
1210
  $screens = apply_filters( 'ig_es_admin_screens', $screens );
@@ -1352,10 +1335,9 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1352
  self::$instance->cron = new ES_Cron();
1353
  self::$instance->compatibiloty = new ES_Compatibility();
1354
  self::$instance->workflows_db = new ES_DB_Workflows();
1355
- self::$instance->carts_db = new IG_ES_DB_WC_Cart();
1356
  self::$instance->trial = new IG_ES_Trial();
1357
 
1358
-
1359
  // Start-IG-Code.
1360
  $name = 'Email Subscribers';
1361
  $plugin = 'email-subscribers';
@@ -1383,11 +1365,11 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1383
  $ig_es_feedback->render_deactivate_feedback();
1384
  }
1385
 
1386
- $plugin_file_path = ES_PLUGIN_DIR . 'email-subscribers.php';
1387
  $allowed_by_default = ES()->is_premium() || ES()->is_trial();
1388
-
1389
  if ( strpos( ES_PLUGIN_DIR, 'email-subscribers-premium' ) ) {
1390
- $plugin_file_path = ES_PLUGIN_DIR . 'email-subscribers-premium.php';
1391
  }
1392
 
1393
  $plugin_usage_tracker_class = 'IG_Plugin_Usage_Tracker_V_' . str_replace( '.', '_', IG_ES_PLUGIN_USAGE_TRACKER_VERSION );
@@ -1406,7 +1388,6 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1406
  if ( ! post_type_exists( 'es_template' ) ) {
1407
  add_action( 'init', array( 'Email_Subscribers_Activator', 'register_email_templates' ) );
1408
  }
1409
-
1410
  }
1411
 
1412
  return self::$instance;
@@ -1414,25 +1395,25 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1414
 
1415
  /**
1416
  * Method to get plugin plan
1417
- *
1418
  * @return string $plan
1419
- *
1420
  * @since 4.6.1
1421
  */
1422
  public function get_plan() {
1423
 
1424
  $plan = apply_filters( 'ig_es_plan', 'lite' );
1425
-
1426
  return $plan;
1427
  }
1428
 
1429
  /**
1430
  * Method to add trial plan
1431
- *
1432
  * @param string $plan
1433
- *
1434
  * @return string $plan
1435
- *
1436
  * @since 4.6.1
1437
  */
1438
  public function add_trial_plan( $plan = '' ) {
@@ -1446,11 +1427,11 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1446
 
1447
  /**
1448
  * Method to add additional plugin usage tracking data specific to Email Subscribers
1449
- *
1450
  * @param array $tracking_data
1451
- *
1452
  * @return array $tracking_data
1453
- *
1454
  * @since 4.7.7
1455
  */
1456
  public function add_tracking_data( $tracking_data = array() ) {
@@ -1463,25 +1444,25 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1463
 
1464
  /**
1465
  * Method to add ES service authentication data.
1466
- *
1467
  * @param array $request_data Service request data.
1468
- *
1469
  * @return array $request_data
1470
- *
1471
  * @since 4.6.1
1472
  */
1473
  public function add_service_authentication_data( $request_data = array() ) {
1474
 
1475
  $es_plan = $this->get_plan();
1476
-
1477
  if ( ! empty( $es_plan ) ) {
1478
  $request_data['plan'] = $es_plan;
1479
  }
1480
-
1481
  if ( $this->is_trial() ) {
1482
 
1483
  $trial_started_at = get_option( 'ig_es_trial_started_at' );
1484
- $site_url = site_url();
1485
 
1486
  $request_data['trial_started_at'] = $trial_started_at;
1487
  $request_data['site_url'] = $site_url;
@@ -1492,12 +1473,12 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1492
 
1493
  /**
1494
  * Method to check if user has given optin consent.
1495
- *
1496
  * @since 4.6.1
1497
  */
1498
  public function check_trial_optin_consent() {
1499
 
1500
- // Check optin consent only if not already trial or premium.
1501
  if ( ! ( $this->is_trial() || $this->is_premium() ) ) {
1502
  $trial_consent = ig_es_get_request_data( 'ig_es_trial_consent', '' );
1503
  if ( ! empty( $trial_consent ) ) {
@@ -1510,21 +1491,21 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1510
  }
1511
  }
1512
  }
1513
-
1514
  /**
1515
  * Method to add trial related data.
1516
- *
1517
  * @param string $is_trial.
1518
- *
1519
  * @return int $trial_started_at
1520
- *
1521
  * @since 4.6.1
1522
  */
1523
  public function add_trial_data( $is_trial = '', $trial_started_at = 0 ) {
1524
 
1525
  $is_trial = ! empty( $is_trial ) ? $is_trial : 'yes';
1526
  update_option( 'ig_es_is_trial', $is_trial, false );
1527
-
1528
  if ( 'yes' === $is_trial ) {
1529
  $trial_started_at = ! empty( $trial_started_at ) ? $trial_started_at : time();
1530
  update_option( 'ig_es_trial_started_at', $trial_started_at, false );
@@ -1533,21 +1514,21 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1533
 
1534
  /**
1535
  * Method to get admin menu title.
1536
- *
1537
  * @return string $menu_title Admin menu title
1538
- *
1539
  * @since 4.6.3
1540
- */
1541
  public function get_admin_menu_title() {
1542
-
1543
  global $ig_es_tracker;
1544
-
1545
  $menu_title = __( 'Email Subscribers', 'email-subscribers' );
1546
 
1547
  if ( 'woo' === IG_ES_PLUGIN_PLAN ) {
1548
  $menu_title = __( 'Icegram', 'email-subscribers' );
1549
 
1550
- $icegram_lite_plugin_slug = 'icegram/icegram.php';
1551
  $icegram_premium_plugin_slug = 'icegram-engage/icegram-engage.php';
1552
 
1553
  $icegram_lite_installed = $ig_es_tracker::is_plugin_installed( $icegram_lite_plugin_slug );
@@ -1564,16 +1545,16 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1564
 
1565
  /**
1566
  * Method to get admin menu page prefix.
1567
- *
1568
  * @return string $page_prefix Admin menu page prefix.
1569
- *
1570
  * @since 4.6.3
1571
  */
1572
  public function get_admin_page_prefix() {
1573
-
1574
  $menu_title = $this->get_admin_menu_title();
1575
  $page_prefix = sanitize_title( $menu_title );
1576
-
1577
  return $page_prefix;
1578
  }
1579
 
@@ -1581,7 +1562,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1581
  * Check whether constant definition is enabled or not.
1582
  *
1583
  * @return bool
1584
- *
1585
  * @since 4.7.0
1586
  */
1587
  public function is_const_enabled() {
@@ -1671,7 +1652,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1671
  }
1672
 
1673
  break;
1674
-
1675
  case 'sparkpost':
1676
  switch ( $key ) {
1677
  case 'api_key':
@@ -1701,7 +1682,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1701
  }
1702
 
1703
  break;
1704
-
1705
  }
1706
 
1707
  return $return;
@@ -1713,7 +1694,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1713
  *
1714
  * @param string $group
1715
  * @param string $key
1716
- * @param mixed $value
1717
  *
1718
  * @since 4.7.0
1719
  *
@@ -1843,10 +1824,10 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1843
  public function get_const_name( $group, $key ) {
1844
 
1845
  $return = '';
1846
-
1847
  if ( $this->is_const_enabled() ) {
1848
  switch ( $group ) {
1849
-
1850
  case 'smtp':
1851
  switch ( $key ) {
1852
  case 'host':
@@ -1868,9 +1849,9 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1868
  $return = 'IG_ES_SMTP_PASSWORD';
1869
  break;
1870
  }
1871
-
1872
  break;
1873
-
1874
  case 'Amazon_SES':
1875
  switch ( $key ) {
1876
  case 'access_key_id':
@@ -1883,9 +1864,9 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1883
  $return = 'IG_ES_AMAZONSES_REGION';
1884
  break;
1885
  }
1886
-
1887
  break;
1888
-
1889
  case 'mailgun':
1890
  switch ( $key ) {
1891
  case 'private_api_key':
@@ -1898,18 +1879,18 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1898
  $return = 'IG_ES_MAILGUN_REGION';
1899
  break;
1900
  }
1901
-
1902
  break;
1903
-
1904
  case 'sendgrid':
1905
  switch ( $key ) {
1906
  case 'api_key':
1907
  $return = 'IG_ES_SENDGRID_API_KEY';
1908
  break;
1909
  }
1910
-
1911
  break;
1912
-
1913
  case 'sparkpost':
1914
  switch ( $key ) {
1915
  case 'api_key':
@@ -1919,16 +1900,16 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1919
  $return = 'IG_ES_SPARKPOST_REGION';
1920
  break;
1921
  }
1922
-
1923
  break;
1924
-
1925
  case 'pepipost':
1926
  switch ( $key ) {
1927
  case 'api_key':
1928
  $return = 'IG_ES_PEPIPOST_API_KEY';
1929
  break;
1930
  }
1931
-
1932
  break;
1933
 
1934
  case 'postmark':
@@ -1937,9 +1918,9 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1937
  $return = 'IG_ES_POSTMARK_API_TOKEN';
1938
  break;
1939
  }
1940
-
1941
  break;
1942
-
1943
  default:
1944
  $return = '';
1945
  }
@@ -1955,7 +1936,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
1955
  * @param string $key Key name.
1956
  *
1957
  * @return $message
1958
- *
1959
  * @since 4.7.0
1960
  */
1961
  public function get_const_set_message( $group, $key ) {
39
  * @since 4.2.1
40
  *
41
  * @var Email_Subscribers The one true Email_Subscribers
 
42
  */
43
  private static $instance;
44
 
47
  *
48
  * @since 4.2.1
49
  * @var object|ES_Queue
 
50
  */
51
  public $queue;
52
 
55
  *
56
  * @since 4.2.1
57
  * @var object|ES_DB_Queue
 
58
  */
59
  public $queue_db;
60
  /**
62
  *
63
  * @since 4.2.1
64
  * @var object|ES_Actions
 
65
  */
66
  public $actions;
67
 
70
  *
71
  * @since 4.3.1
72
  * @var object|ES_Cron
 
73
  */
74
  public $cron;
75
 
78
  *
79
  * @since 4.3.9
80
  * @var object|ES_Compatibility
 
81
  */
82
  public $compatibiloty;
83
 
86
  *
87
  * @since 4.2.1
88
  * @var object|ES_DB_Actions
 
89
  */
90
  public $actions_db;
91
 
95
  * @since 4.2.1
96
  *
97
  * @var $feedback
 
98
  */
99
  public $feedback;
100
 
104
  * @since 4.2.1
105
  *
106
  * @var $tracker
 
107
  */
108
  public $tracker;
109
 
122
  * @since 4.2.1
123
  *
124
  * @var object|ES_DB_Campaigns
 
125
  */
126
  public $campaigns_db;
127
 
130
  *
131
  * @since 4.2.1
132
  * @var object|ES_Lists_Table
 
133
  */
134
  public $lists;
135
 
139
  * @since 4.2.1
140
  *
141
  * @var object|ES_DB_Lists
 
142
  */
143
  public $lists_db;
144
 
147
  *
148
  * @since 4.2.1
149
  * @var object|ES_Forms_Table
 
150
  */
151
  public $forms;
152
 
210
  * @since 4.2.1
211
  *
212
  * @var object|ES_Integrations
 
213
  */
214
  public $integrations;
215
 
219
  * @since 4.2.1
220
  *
221
  * @var object|IG_Logger
 
222
  */
223
  public $logger;
224
 
305
  * @since 4.0.0
306
  */
307
  public function add_admin_notice() {
308
+ // Halloween offer
309
+ $show_offer = false;
310
  $current_page = ig_es_get_request_data( 'page' );
311
+
312
+ if ( $this->can_upsell_features( array( 'lite', 'trial', 'starter' ) ) && IG_ES_Onboarding::is_onboarding_completed() ) {
313
  if ( 'es_reports' === $current_page ) {
314
  $report_insight = ig_es_get_request_data( 'insight' );
315
  if ( ! $report_insight ) {
317
  }
318
  } else {
319
  $show_offer = true;
320
+ }
321
  }
322
 
323
  if ( $show_offer ) {
337
  return;
338
  }
339
 
340
+ // cron notice
341
  $notice_option = get_option( 'ig_es_wp_cron_notice' );
342
 
343
  $show_notice = true;
357
  $disable_wp_cron_notice .= '<br/>' . sprintf( __( 'Or schedule Cron in <a href="%s" target="_blank">cPanel</a>', 'email-subscribers' ), $cpanel_url );
358
  /* translators: %s: ES Pro URL */
359
  $disable_wp_cron_notice .= '<br/>' . sprintf( __( 'Or use <strong><a href="%s" target="_blank">Email Subscribers Pro</a></strong> for automatic Cron support', 'email-subscribers' ), $es_pro_url );
360
+ $html = '<div class="notice notice-warning" style="background-color: #FFF;"><p style="letter-spacing: 0.6px;">' . $disable_wp_cron_notice . '<a style="float:right" class="es-admin-btn es-admin-btn-secondary " href="' . admin_url() . '?es_dismiss_admin_notice=1&option_name=wp_cron_notice">' . __(
361
+ 'OK, I Got it!',
362
+ 'email-subscribers'
363
+ ) . '</a></p></div>';
364
  $args['html'] = $html;
365
  ES_Admin_Notices::add_custom_notice( 'show_wp_cron', $args );
366
  } else {
550
  define( 'IG_ES_MAX_EMAIL_SEND_AT_ONCE', 30 );
551
  }
552
 
 
553
  if ( ! defined( 'IG_ES_CAMPAIGN_STATUS_IN_ACTIVE' ) ) {
554
  define( 'IG_ES_CAMPAIGN_STATUS_IN_ACTIVE', 0 );
555
  }
590
  define( 'IG_ES_MAILING_QUEUE_STATUS_SENT', 'Sent' );
591
  }
592
 
 
593
  if ( ! defined( 'IG_ES_WORKFLOW_STATUS_IN_ACTIVE' ) ) {
594
  define( 'IG_ES_WORKFLOW_STATUS_IN_ACTIVE', 0 );
595
  }
601
  if ( ! defined( 'IG_ES_TRIAL_PERIOD_IN_DAYS' ) ) {
602
  define( 'IG_ES_TRIAL_PERIOD_IN_DAYS', 14 );
603
  }
604
+
605
  if ( ! defined( 'IG_ES_PRODUCT_ID' ) ) {
606
  define( 'IG_ES_PRODUCT_ID', 1002 );
607
  }
635
  * with WordPress.
636
  *
637
  * @since 4.0
 
638
  */
639
  private function load_dependencies() {
640
 
655
  // Admin Notices
656
  'lite/includes/notices/class-es-admin-notices.php',
657
 
 
658
  // Database class files
659
  'lite/includes/db/class-es-db.php',
660
  'lite/includes/db/class-es-db-queue.php',
736
  // Install/ Update
737
  'lite/includes/upgrade/es-update-functions.php',
738
  'lite/includes/class-es-install.php',
739
+
740
  // Onboarding process handler class.
741
  'lite/admin/class-ig-es-onboarding.php',
742
 
755
  // Pro Feature
756
  'lite/includes/pro-features.php',
757
  // End-IG-Code.
758
+
759
  // Feedback Class
760
  'lite/includes/feedback/class-ig-tracker.php',
761
  // Start-IG-Code.
763
  'lite/includes/feedback/class-ig-plugin-usage-tracker.php',
764
  'lite/includes/feedback.php',
765
  // End-IG-Code.
766
+
767
  // WC session tracking
768
  'lite/includes/classes/class-ig-es-wc-session-tracker.php',
769
  'lite/includes/classes/ig-es-wc-cookies.php',
770
+
771
  // Workflows
772
  'lite/includes/workflows/db/class-es-db-workflows.php',
773
  'lite/includes/workflows/db/class-es-db-workflows-queue.php',
778
  'lite/includes/workflows/abstracts/class-es-workflow-action.php',
779
  'lite/includes/workflows/abstracts/class-es-workflow-data-type.php',
780
  'lite/includes/workflows/abstracts/class-ig-es-workflow-variable.php',
781
+
782
  // Workflow Utility
783
  'lite/includes/workflows/class-es-clean.php',
784
  'lite/includes/workflows/class-es-format.php',
793
  // Workflow
794
  'lite/includes/workflows/class-es-workflow.php',
795
  'lite/includes/workflows/class-es-workflow-factory.php',
796
+
797
  // Data Types
798
  'lite/includes/workflows/data-types/abstracts/class-es-data-type-form-data.php',
799
  'lite/includes/workflows/data-types/class-es-data-type-user.php',
800
  'lite/includes/workflows/data-types/class-es-data-type-subscriber.php',
801
  'lite/includes/workflows/class-es-workflow-data-types.php',
802
+
803
  'lite/includes/workflows/variables/class-es-workflow-data-types.php',
804
+
805
  // Data Layer
806
  'lite/includes/workflows/class-es-workflow-data-layer.php',
807
+
808
  // Workflow Fields
809
  'lite/includes/workflows/fields/class-es-field.php',
810
  'lite/includes/workflows/fields/class-es-text.php',
814
  'lite/includes/workflows/fields/class-es-select.php',
815
  'lite/includes/workflows/fields/class-es-checkbox.php',
816
  'lite/includes/workflows/fields/class-es-wp-editor.php',
817
+
818
  // Workflow Admin
819
  'lite/includes/workflows/admin/class-es-workflow-admin.php',
820
  'lite/includes/workflows/admin/class-es-workflow-admin-edit.php',
821
  'lite/includes/workflows/admin/class-es-workflow-admin-ajax.php',
822
+
823
  // Workflow Triggers.
824
  'lite/includes/workflows/triggers/abstracts/class-es-trigger-form-submitted.php',
825
  'lite/includes/workflows/triggers/class-es-trigger-user-registered.php',
826
  'lite/includes/workflows/triggers/class-es-trigger-user-deleted.php',
827
  'lite/includes/workflows/triggers/class-es-trigger-user-updated.php',
828
  'lite/includes/workflows/class-es-workflow-triggers.php',
829
+
830
  // Abstracts workflow actions
831
  'lite/includes/workflows/actions/abstracts/class-ig-es-action-send-email-abstract.php',
832
+
833
  // Workflow Actions.
834
  'lite/includes/workflows/actions/class-es-action-add-to-list.php',
835
  'lite/includes/workflows/actions/class-es-action-move-contact.php',
837
  'lite/includes/workflows/actions/class-es-action-delete-contact.php',
838
  'lite/includes/workflows/actions/class-es-action-update-contact.php',
839
  'lite/includes/workflows/class-es-workflow-actions.php',
840
+
841
  // Workflow Query
842
  'lite/includes/workflows/class-es-workflow-query.php',
843
+
844
+ // Workflow Queue
845
  'lite/includes/workflows/queue/class-es-workflow-queue.php',
846
  'lite/includes/workflows/queue/class-es-workflow-queue-factory.php',
847
  'lite/includes/workflows/queue/class-es-workflow-queue-handler.php',
852
 
853
  // Premium services ui components.
854
  'lite/includes/premium-services-ui/class-ig-es-premium-services-ui.php',
855
+
856
  // Background Process Helper
857
  'lite/includes/classes/class-ig-es-background-process-helper.php',
858
+
859
  // Subscribers Query
860
  'lite/includes/classes/class-ig-es-subscriber-query.php',
861
+
862
+ // Compatibilities
863
+ 'lite/includes/compatibilities/elementor/class-ig-es-compatibility.php',
864
+
865
  // Campaign Rules
866
  'lite/admin/class-ig-es-campaign-rules.php',
867
 
869
  'pro/pro-class-email-subscribers.php',
870
 
871
  );
872
+
873
  foreach ( $files_to_load as $file ) {
874
  if ( is_file( ES_PLUGIN_DIR . $file ) ) {
875
  require_once ES_PLUGIN_DIR . $file;
901
  * of the plugin.
902
  *
903
  * @since 4.0
 
904
  */
905
  private function define_admin_hooks() {
906
 
925
  * of the plugin.
926
  *
927
  * @since 4.0
 
928
  */
929
  private function define_public_hooks() {
930
 
981
 
982
  /**
983
  * Method to get if user has opted for trial or not.
984
+ *
985
  * @return bool
986
+ *
987
  * @since 4.6.0
988
  */
989
  public function is_trial() {
1008
 
1009
  /**
1010
  * Method to get if trial has expired or not.
1011
+ *
1012
  * @return bool
1013
+ *
1014
  * @since 4.6.1
1015
  */
1016
  public function is_trial_expired() {
1020
  if ( 'yes' === $is_trial ) {
1021
  $trial_started_at = get_option( 'ig_es_trial_started_at' );
1022
  if ( ! empty( $trial_started_at ) ) {
1023
+
1024
  // Get current timestamp.
1025
  $current_time = time();
1026
+
1027
  // Get the timestamp when trial will expire.
1028
  $trial_expires_at = $trial_started_at + ES()->trial->get_trial_period();
1029
+
1030
  // Check if current time is greater than expiry time.
1031
  if ( $current_time > $trial_expires_at ) {
1032
  $is_trial_expired = true;
1039
 
1040
  /**
1041
  * Method to check if trial is valid.
1042
+ *
1043
  * @return bool $is_trial_valid Is trial valid
1044
+ *
1045
  * @since 4.6.1
1046
  */
1047
  public function is_trial_valid() {
1052
 
1053
  /**
1054
  * Method to validate a premium service request
1055
+ *
1056
  * @param array $service Request
1057
+ *
1058
  * @return bool
1059
+ *
1060
  * @since 4.6.1
1061
  */
1062
  public function validate_service_request( $services = array() ) {
1063
  $is_request_valid = false;
1064
+
1065
  // Check if trial is still valid.
1066
  if ( $this->is_trial_valid() ) {
1067
  $is_request_valid = true;
1068
+ } elseif ( $this->is_premium() ) {
1069
  $es_services = apply_filters( 'ig_es_services', array() );
1070
  if ( ! empty( $es_services ) ) {
1071
  // Check if there is not any invalid service in $services array which is not present in the $es_services.
1151
  */
1152
  public function can_upsell_features( $show_for_plans = array() ) {
1153
  $es_current_plan = $this->get_plan();
1154
+ if ( in_array( $es_current_plan, $show_for_plans ) ) {
1155
  return true;
1156
  }
1157
  return false;
1188
  "{$prefix}_page_es_pricing",
1189
  "{$prefix}_page_es_sequence",
1190
 
 
1191
  );
1192
 
1193
  $screens = apply_filters( 'ig_es_admin_screens', $screens );
1335
  self::$instance->cron = new ES_Cron();
1336
  self::$instance->compatibiloty = new ES_Compatibility();
1337
  self::$instance->workflows_db = new ES_DB_Workflows();
1338
+ self::$instance->carts_db = new IG_ES_DB_WC_Cart();
1339
  self::$instance->trial = new IG_ES_Trial();
1340
 
 
1341
  // Start-IG-Code.
1342
  $name = 'Email Subscribers';
1343
  $plugin = 'email-subscribers';
1365
  $ig_es_feedback->render_deactivate_feedback();
1366
  }
1367
 
1368
+ $plugin_file_path = ES_PLUGIN_DIR . 'email-subscribers.php';
1369
  $allowed_by_default = ES()->is_premium() || ES()->is_trial();
1370
+
1371
  if ( strpos( ES_PLUGIN_DIR, 'email-subscribers-premium' ) ) {
1372
+ $plugin_file_path = ES_PLUGIN_DIR . 'email-subscribers-premium.php';
1373
  }
1374
 
1375
  $plugin_usage_tracker_class = 'IG_Plugin_Usage_Tracker_V_' . str_replace( '.', '_', IG_ES_PLUGIN_USAGE_TRACKER_VERSION );
1388
  if ( ! post_type_exists( 'es_template' ) ) {
1389
  add_action( 'init', array( 'Email_Subscribers_Activator', 'register_email_templates' ) );
1390
  }
 
1391
  }
1392
 
1393
  return self::$instance;
1395
 
1396
  /**
1397
  * Method to get plugin plan
1398
+ *
1399
  * @return string $plan
1400
+ *
1401
  * @since 4.6.1
1402
  */
1403
  public function get_plan() {
1404
 
1405
  $plan = apply_filters( 'ig_es_plan', 'lite' );
1406
+
1407
  return $plan;
1408
  }
1409
 
1410
  /**
1411
  * Method to add trial plan
1412
+ *
1413
  * @param string $plan
1414
+ *
1415
  * @return string $plan
1416
+ *
1417
  * @since 4.6.1
1418
  */
1419
  public function add_trial_plan( $plan = '' ) {
1427
 
1428
  /**
1429
  * Method to add additional plugin usage tracking data specific to Email Subscribers
1430
+ *
1431
  * @param array $tracking_data
1432
+ *
1433
  * @return array $tracking_data
1434
+ *
1435
  * @since 4.7.7
1436
  */
1437
  public function add_tracking_data( $tracking_data = array() ) {
1444
 
1445
  /**
1446
  * Method to add ES service authentication data.
1447
+ *
1448
  * @param array $request_data Service request data.
1449
+ *
1450
  * @return array $request_data
1451
+ *
1452
  * @since 4.6.1
1453
  */
1454
  public function add_service_authentication_data( $request_data = array() ) {
1455
 
1456
  $es_plan = $this->get_plan();
1457
+
1458
  if ( ! empty( $es_plan ) ) {
1459
  $request_data['plan'] = $es_plan;
1460
  }
1461
+
1462
  if ( $this->is_trial() ) {
1463
 
1464
  $trial_started_at = get_option( 'ig_es_trial_started_at' );
1465
+ $site_url = site_url();
1466
 
1467
  $request_data['trial_started_at'] = $trial_started_at;
1468
  $request_data['site_url'] = $site_url;
1473
 
1474
  /**
1475
  * Method to check if user has given optin consent.
1476
+ *
1477
  * @since 4.6.1
1478
  */
1479
  public function check_trial_optin_consent() {
1480
 
1481
+ // Check optin consent only if not already trial or premium.
1482
  if ( ! ( $this->is_trial() || $this->is_premium() ) ) {
1483
  $trial_consent = ig_es_get_request_data( 'ig_es_trial_consent', '' );
1484
  if ( ! empty( $trial_consent ) ) {
1491
  }
1492
  }
1493
  }
1494
+
1495
  /**
1496
  * Method to add trial related data.
1497
+ *
1498
  * @param string $is_trial.
1499
+ *
1500
  * @return int $trial_started_at
1501
+ *
1502
  * @since 4.6.1
1503
  */
1504
  public function add_trial_data( $is_trial = '', $trial_started_at = 0 ) {
1505
 
1506
  $is_trial = ! empty( $is_trial ) ? $is_trial : 'yes';
1507
  update_option( 'ig_es_is_trial', $is_trial, false );
1508
+
1509
  if ( 'yes' === $is_trial ) {
1510
  $trial_started_at = ! empty( $trial_started_at ) ? $trial_started_at : time();
1511
  update_option( 'ig_es_trial_started_at', $trial_started_at, false );
1514
 
1515
  /**
1516
  * Method to get admin menu title.
1517
+ *
1518
  * @return string $menu_title Admin menu title
1519
+ *
1520
  * @since 4.6.3
1521
+ */
1522
  public function get_admin_menu_title() {
1523
+
1524
  global $ig_es_tracker;
1525
+
1526
  $menu_title = __( 'Email Subscribers', 'email-subscribers' );
1527
 
1528
  if ( 'woo' === IG_ES_PLUGIN_PLAN ) {
1529
  $menu_title = __( 'Icegram', 'email-subscribers' );
1530
 
1531
+ $icegram_lite_plugin_slug = 'icegram/icegram.php';
1532
  $icegram_premium_plugin_slug = 'icegram-engage/icegram-engage.php';
1533
 
1534
  $icegram_lite_installed = $ig_es_tracker::is_plugin_installed( $icegram_lite_plugin_slug );
1545
 
1546
  /**
1547
  * Method to get admin menu page prefix.
1548
+ *
1549
  * @return string $page_prefix Admin menu page prefix.
1550
+ *
1551
  * @since 4.6.3
1552
  */
1553
  public function get_admin_page_prefix() {
1554
+
1555
  $menu_title = $this->get_admin_menu_title();
1556
  $page_prefix = sanitize_title( $menu_title );
1557
+
1558
  return $page_prefix;
1559
  }
1560
 
1562
  * Check whether constant definition is enabled or not.
1563
  *
1564
  * @return bool
1565
+ *
1566
  * @since 4.7.0
1567
  */
1568
  public function is_const_enabled() {
1652
  }
1653
 
1654
  break;
1655
+
1656
  case 'sparkpost':
1657
  switch ( $key ) {
1658
  case 'api_key':
1682
  }
1683
 
1684
  break;
1685
+
1686
  }
1687
 
1688
  return $return;
1694
  *
1695
  * @param string $group
1696
  * @param string $key
1697
+ * @param mixed $value
1698
  *
1699
  * @since 4.7.0
1700
  *
1824
  public function get_const_name( $group, $key ) {
1825
 
1826
  $return = '';
1827
+
1828
  if ( $this->is_const_enabled() ) {
1829
  switch ( $group ) {
1830
+
1831
  case 'smtp':
1832
  switch ( $key ) {
1833
  case 'host':
1849
  $return = 'IG_ES_SMTP_PASSWORD';
1850
  break;
1851
  }
1852
+
1853
  break;
1854
+
1855
  case 'Amazon_SES':
1856
  switch ( $key ) {
1857
  case 'access_key_id':
1864
  $return = 'IG_ES_AMAZONSES_REGION';
1865
  break;
1866
  }
1867
+
1868
  break;
1869
+
1870
  case 'mailgun':
1871
  switch ( $key ) {
1872
  case 'private_api_key':
1879
  $return = 'IG_ES_MAILGUN_REGION';
1880
  break;
1881
  }
1882
+
1883
  break;
1884
+
1885
  case 'sendgrid':
1886
  switch ( $key ) {
1887
  case 'api_key':
1888
  $return = 'IG_ES_SENDGRID_API_KEY';
1889
  break;
1890
  }
1891
+
1892
  break;
1893
+
1894
  case 'sparkpost':
1895
  switch ( $key ) {
1896
  case 'api_key':
1900
  $return = 'IG_ES_SPARKPOST_REGION';
1901
  break;
1902
  }
1903
+
1904
  break;
1905
+
1906
  case 'pepipost':
1907
  switch ( $key ) {
1908
  case 'api_key':
1909
  $return = 'IG_ES_PEPIPOST_API_KEY';
1910
  break;
1911
  }
1912
+
1913
  break;
1914
 
1915
  case 'postmark':
1918
  $return = 'IG_ES_POSTMARK_API_TOKEN';
1919
  break;
1920
  }
1921
+
1922
  break;
1923
+
1924
  default:
1925
  $return = '';
1926
  }
1936
  * @param string $key Key name.
1937
  *
1938
  * @return $message
1939
+ *
1940
  * @since 4.7.0
1941
  */
1942
  public function get_const_set_message( $group, $key ) {
lite/includes/class-es-common.php CHANGED
@@ -33,8 +33,8 @@ class ES_Common {
33
  * Process template body
34
  *
35
  * @param $content
36
- * @param int $tmpl_id
37
- * @param int $campaign_id
38
  *
39
  * @return mixed|string
40
  *
@@ -47,23 +47,24 @@ class ES_Common {
47
 
48
  $content = wpautop( $content );
49
  $content = do_shortcode( shortcode_unautop( $content ) );
50
- $data = array();
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 );
59
- //blog title
60
  $blog_name = get_option( 'blogname' );
61
  $content = str_replace( '{{SITENAME}}', $blog_name, $content );
62
  // site url
63
  $site_url = home_url( '/' );
64
  $content = str_replace( '{{SITEURL}}', $site_url, $content );
65
 
66
- /*TODO: Enable it once Pre header issue fix
 
67
  $meta = ES()->campaigns_db->get_campaign_meta_by_id( $campaign_id );
68
  $meta['pre_header'] = !empty($meta['pre_header']) ? $meta['pre_header'] : '';
69
  if( !empty( $meta['pre_header'] )){
@@ -105,8 +106,8 @@ class ES_Common {
105
  *
106
  * @param string $html HTML for current URL.
107
  * @param string $url Current URL.
108
- * @param array $attr Shortcode attribute.
109
- * @param int $post_ID Current post id.
110
  *
111
  * @return string $html HTML for current URL.
112
  *
@@ -189,7 +190,7 @@ class ES_Common {
189
  $statuses = array(
190
  'subscribed' => __( 'Subscribed', 'email-subscribers' ),
191
  'unconfirmed' => __( 'Unconfirmed', 'email-subscribers' ),
192
- 'unsubscribed' => __( 'Unsubscribed', 'email-subscribers' )
193
  );
194
 
195
  if ( $reverse ) {
@@ -356,14 +357,16 @@ class ES_Common {
356
  $templates = array_merge( $default_template_option, $templates );
357
  }
358
 
359
-
360
  $dropdown = '';
361
  foreach ( $templates as $key => $template ) {
362
- $es_templ_thumbnail = ( ! empty( $template->ID ) ) ? get_the_post_thumbnail_url( $template->ID, array(
363
- '200',
364
- '200'
365
- ) ) : ES_PLUGIN_URL . 'images/envelope.png';
366
- $dropdown .= "<option data-img-url='" . $es_templ_thumbnail . "' value='" . $template->ID . "'";
 
 
 
367
 
368
  if ( absint( $selected ) === absint( $template->ID ) ) {
369
  $dropdown .= ' selected="selected"';
@@ -388,7 +391,7 @@ class ES_Common {
388
  public static function prepare_status_dropdown_options( $selected ) {
389
  $statuses = array(
390
  '1' => __( 'Active', 'email-subscribers' ),
391
- '0' => __( 'Inactive', 'email-subscribers' )
392
  );
393
 
394
  $dropdown = '';
@@ -427,9 +430,9 @@ class ES_Common {
427
  array(
428
  'key' => 'es_template_type',
429
  'value' => $type,
430
- 'compare' => '='
431
- )
432
- )
433
  );
434
 
435
  $es_templates = get_posts( $es_args );
@@ -448,16 +451,20 @@ class ES_Common {
448
  * @since 4.0.0
449
  */
450
  public static function prepare_categories_html( $category_names = array() ) {
451
- $categories = get_terms( array(
452
- 'taxonomy' => 'category',
453
- 'hide_empty' => false,
454
- ) );
 
 
455
  if ( ! is_array( $category_names ) ) {
456
  $category_names = array();
457
  }
458
  $checked_selected = ! array_intersect( array( 'All', 'None' ), $category_names ) ? "checked='checked'" : '';
459
- $category_html = '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;" ><span class="block ml-6 pr-4 text-sm font-normal text-gray-600 pb-1"><input class="es-note-category-parent form-radio text-indigo-600" type="radio" ' . esc_attr( $checked_selected ) . ' value="selected_cat" name="es_note_cat_parent">' . __( 'Select Categories',
460
- 'email-subscribers' ) . '</td></tr>';
 
 
461
  foreach ( $categories as $category ) {
462
 
463
  if ( in_array( $category->term_id, $category_names ) ) {
@@ -469,12 +476,16 @@ class ES_Common {
469
  $category_html .= '<tr class="es-note-child-category"><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><span class="block ml-6 pr-4 text-sm font-normal text-gray-600 pb-1"><input type="checkbox" class="form-checkbox" ' . esc_attr( $checked ) . ' value="' . esc_attr( $category->term_id ) . '" id="es_note_cat[]" name="es_note_cat[]">' . esc_html( $category->name ) . '</td></tr>';
470
  }
471
  $checked_all = in_array( 'All', $category_names ) ? "checked='checked'" : '';
472
- $all_html = '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><span class="block ml-6 pr-4 text-sm font-normal text-gray-600 pb-1"><input type="radio" class="form-radio text-indigo-600 es-note-category-parent" ' . esc_attr( $checked_all ) . ' value="{a}All{a}" name="es_note_cat_parent">' . __( 'All Categories (Also include all categories which will create later)',
473
- 'email-subscribers' ) . '</td></tr>';
 
 
474
 
475
  $checked_none = in_array( 'None', $category_names, true ) ? "checked='checked'" : '';
476
- $none_html = '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><span class="block ml-6 pr-4 text-sm font-normal text-gray-600 pb-1"><input type="radio" class="form-radio text-indigo-600 es-note-category-parent" ' . esc_attr( $checked_none ) . ' value="{a}None{a}" name="es_note_cat_parent">' . __( 'None (Don\'t include post from any category)',
477
- 'email-subscribers' ) . '</td></tr>';
 
 
478
 
479
  return $none_html . $all_html . $category_html;
480
  }
@@ -489,7 +500,11 @@ class ES_Common {
489
  * @since 4.0.0
490
  */
491
  public static function prepare_custom_post_type_checkbox( $custom_post_types ) {
492
- $args = array( 'public' => true, 'exclude_from_search' => false, '_builtin' => false );
 
 
 
 
493
  $output = 'names';
494
  $operator = 'and';
495
  $post_types = get_post_types( $args, $output, $operator );
@@ -504,7 +519,6 @@ class ES_Common {
504
  }
505
  $custom_post_type_html .= '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><span class="block ml-12 pr-4 text-sm font-medium text-gray-600 pb-2"><input type="checkbox" ' . esc_attr( $checked ) . ' value="{T}' . esc_html( $post_type ) . '{T}" id="es_note_cat[]" class="es_custom_post_type form-checkbox" name="es_note_cat[]">' . esc_html( $post_type ) . '</td></tr>';
506
  }
507
-
508
  } else {
509
  $custom_post_type_html = '<tr><span class="block ml-12 pr-4 text-sm font-normal text-gray-600 pb-2">' . __( 'No Custom Post Types Available', 'email-subscribers' ) . '</tr>';
510
  }
@@ -523,7 +537,7 @@ class ES_Common {
523
 
524
  $types = array(
525
  'single_opt_in' => __( 'Single Opt-In', 'email-subscribers' ),
526
- 'double_opt_in' => __( 'Double Opt-In', 'email-subscribers' )
527
  );
528
 
529
  return $types;
@@ -533,7 +547,6 @@ class ES_Common {
533
  * Get options to sending mails of weekly summary.
534
  *
535
  * @return array
536
- *
537
  */
538
  public static function run_summary_cron_on() {
539
 
@@ -554,7 +567,6 @@ class ES_Common {
554
  * Get time options to sending mails of weekly summary.
555
  *
556
  * @return array
557
- *
558
  */
559
  public static function get_railway_hrs_timings() {
560
 
@@ -562,10 +574,10 @@ class ES_Common {
562
 
563
  for ( $i = 1; $i <= 24; $i ++ ) {
564
  if ( $i <= 12 ) {
565
- $timings["{$i}am"] = "{$i}:00 AM";
566
  } else {
567
- $time = $i - 12;
568
- $timings["{$time}pm"] = "{$time}:00 PM";
569
  }
570
  }
571
 
@@ -583,7 +595,7 @@ class ES_Common {
583
  $sizes = array(
584
  'full' => __( 'Full Size', 'email-subscribers' ),
585
  'medium' => __( 'Medium Size', 'email-subscribers' ),
586
- 'thumbnail' => __( 'Thumbnail', 'email-subscribers' )
587
  );
588
 
589
  return $sizes;
@@ -593,7 +605,7 @@ class ES_Common {
593
  * Get IG Option
594
  *
595
  * @param $option
596
- * @param null $default
597
  *
598
  * @return mixed|void|null
599
  *
@@ -677,7 +689,7 @@ class ES_Common {
677
  * Convert categories string to array
678
  *
679
  * @param string $categories_str
680
- * @param bool $keep_ids
681
  *
682
  * @return array|mixed
683
  *
@@ -800,7 +812,7 @@ class ES_Common {
800
  public static function prepare_first_name_last_name( $name = '' ) {
801
  $result = array(
802
  'first_name' => '',
803
- 'last_name' => ''
804
  );
805
 
806
  if ( ! empty( $name ) ) {
@@ -818,7 +830,6 @@ class ES_Common {
818
  $result['last_name'] = trim( $last_name );
819
  }
820
 
821
-
822
  return $result;
823
  }
824
 
@@ -909,7 +920,7 @@ class ES_Common {
909
  'name_required' => 'no',
910
  'list_visible' => 'no',
911
  'lists' => array( $list_id ),
912
- 'af_id' => 0
913
  );
914
 
915
  $prepared_form_data = ES_Forms_Table::prepare_form_data( $data );
@@ -918,12 +929,11 @@ class ES_Common {
918
 
919
  $data_to_set = array(
920
  'title' => $title,
921
- 'form_id' => $inserted_form_id
922
  );
923
 
924
  $es_3_widget_option_data[ $key ] = $data_to_set;
925
  }
926
-
927
  }
928
 
929
  update_option( $latest_widget_option, $es_3_widget_option_data );
@@ -955,7 +965,7 @@ class ES_Common {
955
  'name_required' => 'no',
956
  'list_visible' => 'no',
957
  'lists' => array( $list_id ),
958
- 'af_id' => 0
959
  );
960
 
961
  $prepared_form_data = ES_Forms_Table::prepare_form_data( $data );
@@ -964,7 +974,7 @@ class ES_Common {
964
 
965
  $data_to_set = array(
966
  'title' => $title,
967
- 'form_id' => $inserted_form_id
968
  );
969
 
970
  $es_4_widget_option_data[ $key ] = $data_to_set;
@@ -975,7 +985,7 @@ class ES_Common {
975
  }
976
  }
977
 
978
- //Update sidebars_widgets options.
979
  $sidebars_widgets = get_option( 'sidebars_widgets', '' );
980
  if ( ! empty( $sidebars_widgets ) ) {
981
  $widgets_data = maybe_unserialize( $sidebars_widgets );
@@ -999,7 +1009,6 @@ class ES_Common {
999
 
1000
  update_option( 'sidebars_widgets', $widgets_data );
1001
  }
1002
-
1003
  }
1004
 
1005
  }
@@ -1022,7 +1031,7 @@ class ES_Common {
1022
  *
1023
  * @param string $message
1024
  * @param string $status
1025
- * @param bool $is_dismissible
1026
  *
1027
  * @since 4.1.0
1028
  */
@@ -1093,7 +1102,7 @@ class ES_Common {
1093
  'type' => 'info',
1094
  'center' => true,
1095
  'box_shadow' => true,
1096
- 'show_icon' => true
1097
  );
1098
 
1099
  $info = wp_parse_args( $info, $default_args );
@@ -1153,7 +1162,7 @@ class ES_Common {
1153
  $default_params = array(
1154
  'set_transient' => true,
1155
  'force' => false,
1156
- 'show_once' => false
1157
  );
1158
 
1159
  $params = wp_parse_args( $params, $default_params );
@@ -1270,7 +1279,7 @@ class ES_Common {
1270
  'ig_es_update_tasks_to_process',
1271
  'ig_es_welcome_email_content',
1272
  'ig_es_welcome_email_subject',
1273
- 'ig_es_email_sent_data'
1274
  );
1275
 
1276
  }
@@ -1335,7 +1344,7 @@ class ES_Common {
1335
  'total_newsletters' => $total_newsletters,
1336
  'total_post_notifications' => $total_post_notifications,
1337
  'total_sequences' => $total_sequences,
1338
- 'settings' => self::get_all_settings()
1339
  );
1340
  }
1341
 
@@ -1381,7 +1390,7 @@ class ES_Common {
1381
 
1382
  $email_sent_data_option = 'email_sent_data';
1383
 
1384
- //Get total emails sent in this hour
1385
  $email_sent_data = self::get_ig_option( $email_sent_data_option, array() );
1386
 
1387
  $total_emails_sent = 0;
@@ -1504,23 +1513,23 @@ class ES_Common {
1504
  $blog_articles = array(
1505
  array(
1506
  'title' => __( 'Top 10 Tips on How to Build an Email List', 'email-subscribers' ),
1507
- 'link' => 'https://www.icegram.com/email-list/'
1508
  ),
1509
  array(
1510
  'title' => __( 'Why are Your Email Unsubscribes Increasing and How to Fix Them?', 'email-subscribers' ),
1511
- 'link' => 'https://www.icegram.com/unsubscribes/'
1512
  ),
1513
  array(
1514
  'title' => __( 'Balance Email Marketing and Social Media Marketing', 'email-subscribers' ),
1515
- 'link' => 'https://www.icegram.com/email-marketing-and-social-media-marketing/'
1516
  ),
1517
  array(
1518
  'title' => __( 'Use social proof to grow blog traffic through email', 'email-subscribers' ),
1519
- 'link' => 'https://www.icegram.com/social-proof/'
1520
  ),
1521
  array(
1522
  'title' => __( '5 Simple Tricks to Improve Email Marketing Campaign Results', 'email-subscribers' ),
1523
- 'link' => 'https://www.icegram.com/email-marketing-campaign/'
1524
  ),
1525
  );
1526
 
@@ -1531,13 +1540,13 @@ class ES_Common {
1531
  'title' => __( 'Email Subscribers PRO', 'email-subscribers' ),
1532
  'link' => 'https://www.icegram.com/er6r',
1533
  'label' => __( 'Lifetime', 'email-subscribers' ),
1534
- 'label_class' => 'bg-green-100 text-green-800'
1535
  ),
1536
  array(
1537
  'title' => __( '<b>Email Subscribers Secret Club</b>', 'email-subscribers' ),
1538
  'link' => 'https://www.facebook.com/groups/2298909487017349/',
1539
  'label' => __( 'Join Now', 'email-subscribers' ),
1540
- 'label_class' => 'bg-green-100 text-green-800'
1541
  ),
1542
  );
1543
  }
@@ -1606,7 +1615,6 @@ class ES_Common {
1606
  if ( isset( $settings['captcha'] ) ) {
1607
  return empty( $settings['captcha'] ) ? 'no' : $settings['captcha'];
1608
  }
1609
-
1610
  }
1611
 
1612
  return get_option( 'ig_es_enable_captcha', 'no' );
@@ -1644,11 +1652,15 @@ class ES_Common {
1644
  if ( function_exists( 'wp_encode_emoji' ) ) {
1645
  $string = wp_encode_emoji( $string );
1646
  } else {
1647
- $string = preg_replace( '%(?:
 
1648
  \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
1649
  | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
1650
  | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
1651
- )%xs', '', $string );
 
 
 
1652
  }
1653
  }
1654
 
@@ -1730,7 +1742,7 @@ class ES_Common {
1730
  * Get Campaign Statuses
1731
  *
1732
  * @param string $campaign_type
1733
- * @param bool $reverse
1734
  *
1735
  * @return array
1736
  *
@@ -1843,7 +1855,7 @@ class ES_Common {
1843
 
1844
  $coupons[ $coupon ] = array(
1845
  'last_shown_time' => time(),
1846
- 'count' => $shown_count + 1
1847
  );
1848
 
1849
  update_option( 'ig_es_coupons', $coupons );
@@ -1965,13 +1977,13 @@ class ES_Common {
1965
  if ( ( ( $ig_current_date < strtotime( '2020-11-24' ) ) || ( $ig_current_date > strtotime( '2020-12-02' ) ) ) && self::can_show_coupon( 'PREMIUM10' ) ) {
1966
  ?>
1967
  <p class="mb-1 mt-3">
1968
- <?php
1969
- echo wp_kses_post( __( 'Upgrade now & get <b> 10% discount!</b> <br/><br/>Use coupon code:' ), 'email-subscribers' );
1970
  ?>
1971
 
1972
  <span class="ml-2 px-1.5 py-1 font-medium bg-yellow-100 rounded-md border-2 border-dotted border-indigo-300 select-all"><?php echo esc_html( 'PREMIUM10' ); ?> </span>
1973
  </p>
1974
- <?php
1975
  }
1976
  if ( $upsell_info['cta_html'] ) {
1977
  ?>
@@ -1979,8 +1991,10 @@ class ES_Common {
1979
  <a href="<?php echo esc_url( $upsell_info['pricing_url'] ); ?>" target="_blank"
1980
  class="rounded-md border border-transparent px-3 py-2 bg-white text-sm leading-7 font-medium text-white bg-indigo-600 hover:text-white hover:bg-indigo-500 transition ease-in-out duration-150 mt-2">
1981
  <?php
1982
- esc_html_e( 'Upgrade',
1983
- 'email-subscribers' );
 
 
1984
  ?>
1985
  </a>
1986
  </div>
@@ -2097,7 +2111,7 @@ class ES_Common {
2097
  /**
2098
  * Override wp editor tinymce formatting options
2099
  *
2100
- * @param array $init
2101
  * @param string $editor_id
2102
  *
2103
  * @return array $init
@@ -2179,7 +2193,7 @@ class ES_Common {
2179
  case '':
2180
  ?>
2181
  <span class="inline-flex px-2 text-red-800 bg-red-100 rounded-full"><?php esc_html__( 'Inactive', 'email-subscribers' ); ?></span>
2182
- <?php
2183
  }
2184
 
2185
  $status = ob_get_clean();
33
  * Process template body
34
  *
35
  * @param $content
36
+ * @param int $tmpl_id
37
+ * @param int $campaign_id
38
  *
39
  * @return mixed|string
40
  *
47
 
48
  $content = wpautop( $content );
49
  $content = do_shortcode( shortcode_unautop( $content ) );
50
+ $data = array();
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 );
59
+ // blog title
60
  $blog_name = get_option( 'blogname' );
61
  $content = str_replace( '{{SITENAME}}', $blog_name, $content );
62
  // site url
63
  $site_url = home_url( '/' );
64
  $content = str_replace( '{{SITEURL}}', $site_url, $content );
65
 
66
+ /*
67
+ TODO: Enable it once Pre header issue fix
68
  $meta = ES()->campaigns_db->get_campaign_meta_by_id( $campaign_id );
69
  $meta['pre_header'] = !empty($meta['pre_header']) ? $meta['pre_header'] : '';
70
  if( !empty( $meta['pre_header'] )){
106
  *
107
  * @param string $html HTML for current URL.
108
  * @param string $url Current URL.
109
+ * @param array $attr Shortcode attribute.
110
+ * @param int $post_ID Current post id.
111
  *
112
  * @return string $html HTML for current URL.
113
  *
190
  $statuses = array(
191
  'subscribed' => __( 'Subscribed', 'email-subscribers' ),
192
  'unconfirmed' => __( 'Unconfirmed', 'email-subscribers' ),
193
+ 'unsubscribed' => __( 'Unsubscribed', 'email-subscribers' ),
194
  );
195
 
196
  if ( $reverse ) {
357
  $templates = array_merge( $default_template_option, $templates );
358
  }
359
 
 
360
  $dropdown = '';
361
  foreach ( $templates as $key => $template ) {
362
+ $es_templ_thumbnail = ( ! empty( $template->ID ) ) ? get_the_post_thumbnail_url(
363
+ $template->ID,
364
+ array(
365
+ '200',
366
+ '200',
367
+ )
368
+ ) : ES_PLUGIN_URL . 'images/envelope.png';
369
+ $dropdown .= "<option data-img-url='" . $es_templ_thumbnail . "' value='" . $template->ID . "'";
370
 
371
  if ( absint( $selected ) === absint( $template->ID ) ) {
372
  $dropdown .= ' selected="selected"';
391
  public static function prepare_status_dropdown_options( $selected ) {
392
  $statuses = array(
393
  '1' => __( 'Active', 'email-subscribers' ),
394
+ '0' => __( 'Inactive', 'email-subscribers' ),
395
  );
396
 
397
  $dropdown = '';
430
  array(
431
  'key' => 'es_template_type',
432
  'value' => $type,
433
+ 'compare' => '=',
434
+ ),
435
+ ),
436
  );
437
 
438
  $es_templates = get_posts( $es_args );
451
  * @since 4.0.0
452
  */
453
  public static function prepare_categories_html( $category_names = array() ) {
454
+ $categories = get_terms(
455
+ array(
456
+ 'taxonomy' => 'category',
457
+ 'hide_empty' => false,
458
+ )
459
+ );
460
  if ( ! is_array( $category_names ) ) {
461
  $category_names = array();
462
  }
463
  $checked_selected = ! array_intersect( array( 'All', 'None' ), $category_names ) ? "checked='checked'" : '';
464
+ $category_html = '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;" ><span class="block ml-6 pr-4 text-sm font-normal text-gray-600 pb-1"><input class="es-note-category-parent form-radio text-indigo-600" type="radio" ' . esc_attr( $checked_selected ) . ' value="selected_cat" name="es_note_cat_parent">' . __(
465
+ 'Select Categories',
466
+ 'email-subscribers'
467
+ ) . '</td></tr>';
468
  foreach ( $categories as $category ) {
469
 
470
  if ( in_array( $category->term_id, $category_names ) ) {
476
  $category_html .= '<tr class="es-note-child-category"><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><span class="block ml-6 pr-4 text-sm font-normal text-gray-600 pb-1"><input type="checkbox" class="form-checkbox" ' . esc_attr( $checked ) . ' value="' . esc_attr( $category->term_id ) . '" id="es_note_cat[]" name="es_note_cat[]">' . esc_html( $category->name ) . '</td></tr>';
477
  }
478
  $checked_all = in_array( 'All', $category_names ) ? "checked='checked'" : '';
479
+ $all_html = '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><span class="block ml-6 pr-4 text-sm font-normal text-gray-600 pb-1"><input type="radio" class="form-radio text-indigo-600 es-note-category-parent" ' . esc_attr( $checked_all ) . ' value="{a}All{a}" name="es_note_cat_parent">' . __(
480
+ 'All Categories (Also include all categories which will create later)',
481
+ 'email-subscribers'
482
+ ) . '</td></tr>';
483
 
484
  $checked_none = in_array( 'None', $category_names, true ) ? "checked='checked'" : '';
485
+ $none_html = '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><span class="block ml-6 pr-4 text-sm font-normal text-gray-600 pb-1"><input type="radio" class="form-radio text-indigo-600 es-note-category-parent" ' . esc_attr( $checked_none ) . ' value="{a}None{a}" name="es_note_cat_parent">' . __(
486
+ 'None (Don\'t include post from any category)',
487
+ 'email-subscribers'
488
+ ) . '</td></tr>';
489
 
490
  return $none_html . $all_html . $category_html;
491
  }
500
  * @since 4.0.0
501
  */
502
  public static function prepare_custom_post_type_checkbox( $custom_post_types ) {
503
+ $args = array(
504
+ 'public' => true,
505
+ 'exclude_from_search' => false,
506
+ '_builtin' => false,
507
+ );
508
  $output = 'names';
509
  $operator = 'and';
510
  $post_types = get_post_types( $args, $output, $operator );
519
  }
520
  $custom_post_type_html .= '<tr><td style="padding-top:4px;padding-bottom:4px;padding-right:10px;"><span class="block ml-12 pr-4 text-sm font-medium text-gray-600 pb-2"><input type="checkbox" ' . esc_attr( $checked ) . ' value="{T}' . esc_html( $post_type ) . '{T}" id="es_note_cat[]" class="es_custom_post_type form-checkbox" name="es_note_cat[]">' . esc_html( $post_type ) . '</td></tr>';
521
  }
 
522
  } else {
523
  $custom_post_type_html = '<tr><span class="block ml-12 pr-4 text-sm font-normal text-gray-600 pb-2">' . __( 'No Custom Post Types Available', 'email-subscribers' ) . '</tr>';
524
  }
537
 
538
  $types = array(
539
  'single_opt_in' => __( 'Single Opt-In', 'email-subscribers' ),
540
+ 'double_opt_in' => __( 'Double Opt-In', 'email-subscribers' ),
541
  );
542
 
543
  return $types;
547
  * Get options to sending mails of weekly summary.
548
  *
549
  * @return array
 
550
  */
551
  public static function run_summary_cron_on() {
552
 
567
  * Get time options to sending mails of weekly summary.
568
  *
569
  * @return array
 
570
  */
571
  public static function get_railway_hrs_timings() {
572
 
574
 
575
  for ( $i = 1; $i <= 24; $i ++ ) {
576
  if ( $i <= 12 ) {
577
+ $timings[ "{$i}am" ] = "{$i}:00 AM";
578
  } else {
579
+ $time = $i - 12;
580
+ $timings[ "{$time}pm" ] = "{$time}:00 PM";
581
  }
582
  }
583
 
595
  $sizes = array(
596
  'full' => __( 'Full Size', 'email-subscribers' ),
597
  'medium' => __( 'Medium Size', 'email-subscribers' ),
598
+ 'thumbnail' => __( 'Thumbnail', 'email-subscribers' ),
599
  );
600
 
601
  return $sizes;
605
  * Get IG Option
606
  *
607
  * @param $option
608
+ * @param null $default
609
  *
610
  * @return mixed|void|null
611
  *
689
  * Convert categories string to array
690
  *
691
  * @param string $categories_str
692
+ * @param bool $keep_ids
693
  *
694
  * @return array|mixed
695
  *
812
  public static function prepare_first_name_last_name( $name = '' ) {
813
  $result = array(
814
  'first_name' => '',
815
+ 'last_name' => '',
816
  );
817
 
818
  if ( ! empty( $name ) ) {
830
  $result['last_name'] = trim( $last_name );
831
  }
832
 
 
833
  return $result;
834
  }
835
 
920
  'name_required' => 'no',
921
  'list_visible' => 'no',
922
  'lists' => array( $list_id ),
923
+ 'af_id' => 0,
924
  );
925
 
926
  $prepared_form_data = ES_Forms_Table::prepare_form_data( $data );
929
 
930
  $data_to_set = array(
931
  'title' => $title,
932
+ 'form_id' => $inserted_form_id,
933
  );
934
 
935
  $es_3_widget_option_data[ $key ] = $data_to_set;
936
  }
 
937
  }
938
 
939
  update_option( $latest_widget_option, $es_3_widget_option_data );
965
  'name_required' => 'no',
966
  'list_visible' => 'no',
967
  'lists' => array( $list_id ),
968
+ 'af_id' => 0,
969
  );
970
 
971
  $prepared_form_data = ES_Forms_Table::prepare_form_data( $data );
974
 
975
  $data_to_set = array(
976
  'title' => $title,
977
+ 'form_id' => $inserted_form_id,
978
  );
979
 
980
  $es_4_widget_option_data[ $key ] = $data_to_set;
985
  }
986
  }
987
 
988
+ // Update sidebars_widgets options.
989
  $sidebars_widgets = get_option( 'sidebars_widgets', '' );
990
  if ( ! empty( $sidebars_widgets ) ) {
991
  $widgets_data = maybe_unserialize( $sidebars_widgets );
1009
 
1010
  update_option( 'sidebars_widgets', $widgets_data );
1011
  }
 
1012
  }
1013
 
1014
  }
1031
  *
1032
  * @param string $message
1033
  * @param string $status
1034
+ * @param bool $is_dismissible
1035
  *
1036
  * @since 4.1.0
1037
  */
1102
  'type' => 'info',
1103
  'center' => true,
1104
  'box_shadow' => true,
1105
+ 'show_icon' => true,
1106
  );
1107
 
1108
  $info = wp_parse_args( $info, $default_args );
1162
  $default_params = array(
1163
  'set_transient' => true,
1164
  'force' => false,
1165
+ 'show_once' => false,
1166
  );
1167
 
1168
  $params = wp_parse_args( $params, $default_params );
1279
  'ig_es_update_tasks_to_process',
1280
  'ig_es_welcome_email_content',
1281
  'ig_es_welcome_email_subject',
1282
+ 'ig_es_email_sent_data',
1283
  );
1284
 
1285
  }
1344
  'total_newsletters' => $total_newsletters,
1345
  'total_post_notifications' => $total_post_notifications,
1346
  'total_sequences' => $total_sequences,
1347
+ 'settings' => self::get_all_settings(),
1348
  );
1349
  }
1350
 
1390
 
1391
  $email_sent_data_option = 'email_sent_data';
1392
 
1393
+ // Get total emails sent in this hour
1394
  $email_sent_data = self::get_ig_option( $email_sent_data_option, array() );
1395
 
1396
  $total_emails_sent = 0;
1513
  $blog_articles = array(
1514
  array(
1515
  'title' => __( 'Top 10 Tips on How to Build an Email List', 'email-subscribers' ),
1516
+ 'link' => 'https://www.icegram.com/email-list/',
1517
  ),
1518
  array(
1519
  'title' => __( 'Why are Your Email Unsubscribes Increasing and How to Fix Them?', 'email-subscribers' ),
1520
+ 'link' => 'https://www.icegram.com/unsubscribes/',
1521
  ),
1522
  array(
1523
  'title' => __( 'Balance Email Marketing and Social Media Marketing', 'email-subscribers' ),
1524
+ 'link' => 'https://www.icegram.com/email-marketing-and-social-media-marketing/',
1525
  ),
1526
  array(
1527
  'title' => __( 'Use social proof to grow blog traffic through email', 'email-subscribers' ),
1528
+ 'link' => 'https://www.icegram.com/social-proof/',
1529
  ),
1530
  array(
1531
  'title' => __( '5 Simple Tricks to Improve Email Marketing Campaign Results', 'email-subscribers' ),
1532
+ 'link' => 'https://www.icegram.com/email-marketing-campaign/',
1533
  ),
1534
  );
1535
 
1540
  'title' => __( 'Email Subscribers PRO', 'email-subscribers' ),
1541
  'link' => 'https://www.icegram.com/er6r',
1542
  'label' => __( 'Lifetime', 'email-subscribers' ),
1543
+ 'label_class' => 'bg-green-100 text-green-800',
1544
  ),
1545
  array(
1546
  'title' => __( '<b>Email Subscribers Secret Club</b>', 'email-subscribers' ),
1547
  'link' => 'https://www.facebook.com/groups/2298909487017349/',
1548
  'label' => __( 'Join Now', 'email-subscribers' ),
1549
+ 'label_class' => 'bg-green-100 text-green-800',
1550
  ),
1551
  );
1552
  }
1615
  if ( isset( $settings['captcha'] ) ) {
1616
  return empty( $settings['captcha'] ) ? 'no' : $settings['captcha'];
1617
  }
 
1618
  }
1619
 
1620
  return get_option( 'ig_es_enable_captcha', 'no' );
1652
  if ( function_exists( 'wp_encode_emoji' ) ) {
1653
  $string = wp_encode_emoji( $string );
1654
  } else {
1655
+ $string = preg_replace(
1656
+ '%(?:
1657
  \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
1658
  | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
1659
  | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
1660
+ )%xs',
1661
+ '',
1662
+ $string
1663
+ );
1664
  }
1665
  }
1666
 
1742
  * Get Campaign Statuses
1743
  *
1744
  * @param string $campaign_type
1745
+ * @param bool $reverse
1746
  *
1747
  * @return array
1748
  *
1855
 
1856
  $coupons[ $coupon ] = array(
1857
  'last_shown_time' => time(),
1858
+ 'count' => $shown_count + 1,
1859
  );
1860
 
1861
  update_option( 'ig_es_coupons', $coupons );
1977
  if ( ( ( $ig_current_date < strtotime( '2020-11-24' ) ) || ( $ig_current_date > strtotime( '2020-12-02' ) ) ) && self::can_show_coupon( 'PREMIUM10' ) ) {
1978
  ?>
1979
  <p class="mb-1 mt-3">
1980
+ <?php
1981
+ echo wp_kses_post( __( 'Upgrade now & get <b> 10% discount!</b> <br/><br/>Use coupon code:' ), 'email-subscribers' );
1982
  ?>
1983
 
1984
  <span class="ml-2 px-1.5 py-1 font-medium bg-yellow-100 rounded-md border-2 border-dotted border-indigo-300 select-all"><?php echo esc_html( 'PREMIUM10' ); ?> </span>
1985
  </p>
1986
+ <?php
1987
  }
1988
  if ( $upsell_info['cta_html'] ) {
1989
  ?>
1991
  <a href="<?php echo esc_url( $upsell_info['pricing_url'] ); ?>" target="_blank"
1992
  class="rounded-md border border-transparent px-3 py-2 bg-white text-sm leading-7 font-medium text-white bg-indigo-600 hover:text-white hover:bg-indigo-500 transition ease-in-out duration-150 mt-2">
1993
  <?php
1994
+ esc_html_e(
1995
+ 'Upgrade',
1996
+ 'email-subscribers'
1997
+ );
1998
  ?>
1999
  </a>
2000
  </div>
2111
  /**
2112
  * Override wp editor tinymce formatting options
2113
  *
2114
+ * @param array $init
2115
  * @param string $editor_id
2116
  *
2117
  * @return array $init
2193
  case '':
2194
  ?>
2195
  <span class="inline-flex px-2 text-red-800 bg-red-100 rounded-full"><?php esc_html__( 'Inactive', 'email-subscribers' ); ?></span>
2196
+ <?php
2197
  }
2198
 
2199
  $status = ob_get_clean();
lite/includes/class-es-install.php CHANGED
@@ -21,10 +21,9 @@ if ( ! class_exists( 'ES_Install' ) ) {
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
  /**
@@ -32,43 +31,42 @@ if ( ! class_exists( 'ES_Install' ) ) {
32
  *
33
  * @since 4.0.0
34
  * @var array
35
- *
36
  */
37
  private static $db_updates = array(
38
 
39
- '3.2.0' => array(
40
  'ig_es_update_320_add_sync_option',
41
- 'ig_es_update_320_db_version'
42
  ),
43
 
44
- '3.2.7' => array(
45
  'ig_es_update_327_change_email_type',
46
- 'ig_es_update_327_db_version'
47
  ),
48
 
49
- '3.3.0' => array(
50
  'ig_es_update_330_import_options',
51
- 'ig_es_update_330_db_version'
52
  ),
53
 
54
- '3.3.6' => array(
55
  'ig_es_update_336_add_template_slug',
56
- 'ig_es_update_336_db_version'
57
  ),
58
 
59
- '3.4.0' => array(
60
  'ig_es_update_340_migrate_templates_to_cpt',
61
  'ig_es_update_340_migrate_keywords',
62
- 'ig_es_update_340_db_version'
63
  ),
64
 
65
  '3.5.16' => array(
66
  'ig_es_update_3516_create_subscribers_ips_table',
67
- 'ig_es_update_3516_db_version'
68
  ),
69
 
70
 
71
- '4.0.0' => array(
72
  /**
73
  * - Create Tables
74
  * - Import Options
@@ -88,40 +86,40 @@ if ( ! class_exists( 'ES_Install' ) ) {
88
  'ig_es_update_400_migrate_post_notifications',
89
  'ig_es_update_400_migrate_notifications',
90
  'ig_es_update_400_migrate_group_selectors_forms',
91
- 'ig_es_update_400_db_version'
92
  ),
93
 
94
- '4.0.1' => array(
95
  'ig_es_update_401_migrate_newsletters',
96
- 'ig_es_update_401_db_version'
97
  ),
98
 
99
- '4.0.2' => array(
100
  'ig_es_update_402_migrate_post_notification_es_template_type',
101
- 'ig_es_update_402_db_version'
102
  ),
103
 
104
- '4.0.3' => array(
105
  'ig_es_update_403_alter_campaigns_table',
106
  'ig_es_update_403_alter_mailing_queue_table',
107
- 'ig_es_update_403_db_version'
108
  ),
109
 
110
- '4.0.5' => array(
111
  'ig_es_update_405_alter_forms_table',
112
  'ig_es_update_405_alter_lists_table',
113
  'ig_es_update_405_migrate_widgets',
114
- 'ig_es_update_405_db_version'
115
  ),
116
 
117
  '4.0.10' => array(
118
- 'ig_es_update_4010_db_version'
119
  ),
120
 
121
  '4.0.11' => array(
122
  'ig_es_update_4011_migrate_newsletter_es_template_type',
123
  'ig_es_update_4011_update_campaign_id_in_mailing_queue',
124
- 'ig_es_update_4011_db_version'
125
  ),
126
 
127
  '4.0.15' => array(
@@ -129,126 +127,126 @@ if ( ! class_exists( 'ES_Install' ) ) {
129
  'ig_es_update_4015_db_version',
130
  ),
131
 
132
- '4.1.1' => array(
133
  'ig_es_update_411_alter_contacts_table',
134
- 'ig_es_update_411_db_version'
135
  ),
136
 
137
- '4.1.7' => array(
138
  'ig_es_update_417_alter_campaigns_table',
139
  'ig_es_update_417_alter_mailing_queue_table',
140
- 'ig_es_update_417_db_version'
141
  ),
142
 
143
  '4.1.13' => array(
144
  'ig_es_update_4113_migrate_categories_in_campaigns_table',
145
  'ig_es_update_4113_create_files',
146
- 'ig_es_update_4113_db_version'
147
  ),
148
  '4.1.15' => array(
149
  'ig_es_update_4115_add_form_submission_option',
150
  'ig_es_update_4115_migrate_db_update_history',
151
- 'ig_es_update_4115_db_version'
152
  ),
153
 
154
- '4.2.0' => array(
155
  'ig_es_update_420_alter_campaigns_table',
156
  'ig_es_update_420_create_tables',
157
  'ig_es_update_420_migrate_mailer_options',
158
- 'ig_es_update_420_db_version'
159
  ),
160
 
161
- '4.2.1' => array(
162
  'ig_es_update_421_drop_tables',
163
  'ig_es_update_421_create_tables',
164
- 'ig_es_update_421_db_version'
165
  ),
166
 
167
- '4.2.4' => array(
168
  'ig_es_update_424_drop_tables',
169
  'ig_es_update_424_create_tables',
170
- 'ig_es_update_424_db_version'
171
  ),
172
 
173
- '4.3.0' => array(
174
  'ig_es_update_430_alter_campaigns_table',
175
- 'ig_es_update_430_db_version'
176
  ),
177
 
178
- '4.3.1' => array(
179
  'ig_es_update_431_set_default_permissions',
180
  'ig_es_update_431_permanently_delete_lists',
181
  'ig_es_update_431_permanently_delete_forms',
182
  'ig_es_update_431_disable_autoload_options',
183
- 'ig_es_update_431_db_version'
184
  ),
185
 
186
- '4.3.2' => array(
187
  'ig_es_update_432_import_bfcm_templates',
188
- 'ig_es_update_432_db_version'
189
  ),
190
 
191
- '4.3.4' => array(
192
  'ig_es_update_434_permanently_delete_campaigns',
193
- 'ig_es_update_434_db_version'
194
  ),
195
 
196
- '4.4.1' => array(
197
  'ig_es_update_441_create_tables',
198
  'ig_es_update_441_migrate_audience_sync_settings',
199
- 'ig_es_update_441_db_version'
200
  ),
201
 
202
- '4.4.2' => array(
203
  'ig_es_update_442_set_workflows_default_permission',
204
- 'ig_es_update_442_db_version'
205
  ),
206
 
207
- '4.4.9' => array(
208
  'ig_es_update_449_create_tables',
209
- 'ig_es_update_449_db_version'
210
  ),
211
 
212
  '4.4.10' => array(
213
  'ig_es_update_4410_load_templates',
214
- 'ig_es_update_4410_db_version'
215
  ),
216
 
217
- '4.5.0' => array(
218
  'ig_es_update_450_alter_actions_table',
219
- 'ig_es_update_450_db_version'
220
  ),
221
 
222
- '4.5.7' => array(
223
  'ig_es_update_457_alter_list_table',
224
  'ig_es_update_457_add_list_hash',
225
  'ig_es_update_457_db_version',
226
  ),
227
 
228
- '4.6.3' => array(
229
  'ig_es_update_463_alter_contacts_table',
230
  'ig_es_migrate_ip_from_list_contacts_to_contacts_table',
231
  'ig_es_update_463_db_version',
232
  ),
233
 
234
- '4.6.5' => array(
235
  'ig_es_update_465_create_tables',
236
  'ig_es_update_465_db_version',
237
  ),
238
- '4.6.6' => array(
239
  'ig_es_update_466_create_temp_import_table',
240
  'ig_es_update_466_db_version',
241
  ),
242
- '4.6.7' => array(
243
  'ig_es_update_467_alter_contacts_table',
244
  'ig_es_add_country_code_to_contacts_table',
245
  'ig_es_update_467_db_version',
246
  ),
247
- '4.6.8' => array(
248
  'ig_es_update_468_create_unsubscribe_feedback_table',
249
  'ig_es_update_468_db_version',
250
  ),
251
- '4.6.9' => array(
252
  'ig_es_update_469_alter_wc_guests_table',
253
  'ig_es_update_469_db_version',
254
  ),
@@ -256,11 +254,11 @@ if ( ! class_exists( 'ES_Install' ) ) {
256
  'ig_es_migrate_4613_sequence_list_settings_into_campaign_rules',
257
  'ig_es_update_4613_db_version',
258
  ),
259
- '4.7.8' => array(
260
  'ig_es_add_index_to_list_contacts_table',
261
  'ig_es_update_478_db_version',
262
  ),
263
- '4.7.9' => array(
264
  'ig_es_add_primay_key_to_actions_table',
265
  'ig_es_update_479_db_version',
266
  ),
@@ -324,13 +322,13 @@ if ( ! class_exists( 'ES_Install' ) ) {
324
 
325
  self::update( true );
326
 
327
- //ES_Admin_Notices::add_notice( 'update' );
328
  }
329
 
330
  if ( ! empty( $_GET['force_update_ig_es'] ) ) {
331
  check_admin_referer( 'ig_es_force_db_update', 'ig_es_force_db_update_nonce' );
332
  self::update();
333
- //ES_Admin_Notices::add_notice( 'update' );
334
  wp_safe_redirect( admin_url( 'admin.php?page=es_settings' ) );
335
  exit;
336
  }
@@ -346,7 +344,6 @@ if ( ! class_exists( 'ES_Install' ) ) {
346
  // Create Files
347
  self::create_files();
348
 
349
-
350
  if ( ! is_blog_installed() ) {
351
  self::$logger->error( 'Blog is not installed.', self::$logger_context );
352
 
@@ -424,7 +421,6 @@ if ( ! class_exists( 'ES_Install' ) ) {
424
  *
425
  * If we found 'current_sa_email_subscribers_db_version' option, which means it's a
426
  * migration from ES 3.5.x
427
- *
428
  */
429
  return is_null( get_option( 'ig_es_db_version', null ) ) && is_null( get_option( 'current_sa_email_subscribers_db_version', null ) ) && is_null( get_option( 'email-subscribers', null ) );
430
  }
@@ -475,7 +471,7 @@ if ( ! class_exists( 'ES_Install' ) ) {
475
  self::update();
476
  } else {
477
  self::$logger->info( 'Show update notice.', self::$logger_context );
478
- //ES_Admin_Notices::add_notice( 'update' );
479
  }
480
  } else {
481
  self::$logger->info( 'Database is upto date' );
@@ -588,7 +584,7 @@ if ( ! class_exists( 'ES_Install' ) ) {
588
  foreach ( $batch as $key => $value ) {
589
 
590
  $is_value_exists = true;
591
- //$task_transient = $value . '_processed';
592
  $ig_es_update_processed_tasks = get_option( 'ig_es_update_processed_tasks', array() );
593
  $task = false; // By default it's set to false
594
 
@@ -612,13 +608,12 @@ if ( ! class_exists( 'ES_Install' ) ) {
612
 
613
  unset( $batch[ $key ] );
614
  }
615
-
616
  }
617
 
618
  update_option( 'ig_es_update_tasks_to_process', $batch );
619
  }
620
 
621
- //Delete update transient
622
  delete_transient( 'ig_es_updating' );
623
  }
624
 
@@ -713,7 +708,7 @@ if ( ! class_exists( 'ES_Install' ) ) {
713
  $sender_details['name'] = $blog_name;
714
  $sender_details['email'] = $admin_email;
715
 
716
- //check if installed WP Mail SMTP
717
  if ( in_array( 'wp-mail-smtp/wp_mail_smtp.php', $active_plugins ) ) {
718
  $wp_mail_smtp_settings = get_option( 'wp_mail_smtp', array() );
719
 
@@ -745,7 +740,7 @@ if ( ! class_exists( 'ES_Install' ) ) {
745
  $latest_db_version = self::get_latest_db_version_to_update();
746
 
747
  $ig_es_db_update_history = array(
748
- $latest_db_version => ig_get_current_date_time()
749
  );
750
 
751
  $sender_details = self::get_sender_details();
@@ -757,7 +752,7 @@ if ( ! class_exists( 'ES_Install' ) ) {
757
  $guid = ES_Common::generate_guid( 6 );
758
  $cronurl = $home_url . '?es=cron&guid=' . $guid;
759
 
760
- $report = '';
761
  $report .= "Hi Admin,\n\n";
762
  $report .= "Email has been sent successfully to {{COUNT}} email(s). Please find the details below:\n\n";
763
  $report .= "Unique ID: {{UNIQUE}}\n";
@@ -766,7 +761,6 @@ if ( ! class_exists( 'ES_Install' ) ) {
766
  $report .= "For more information, login to your dashboard and go to Reports menu in Email Subscribers.\n\n";
767
  $report .= 'Thank You.';
768
 
769
-
770
  $new_contact_email_subject = 'One more contact joins our tribe!';
771
  $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...";
772
 
@@ -785,58 +779,197 @@ if ( ! class_exists( 'ES_Install' ) ) {
785
  $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";
786
 
787
  $options = array(
788
- 'ig_es_from_name' => array( 'default' => $sender_details['name'], 'old_option' => 'ig_es_fromname' ),
789
- 'ig_es_from_email' => array( 'default' => $sender_details['email'], 'old_option' => 'ig_es_fromemail' ),
790
- 'ig_es_admin_new_contact_email_subject' => array( 'default' => $new_contact_email_subject, 'old_option' => 'ig_es_admin_new_sub_subject' ),
791
- 'ig_es_admin_new_contact_email_content' => array( 'default' => $new_contact_email_content, 'old_option' => 'ig_es_admin_new_sub_content' ),
792
- 'ig_es_admin_emails' => array( 'default' => $admin_email, 'old_option' => 'ig_es_adminemail' ),
793
- 'ig_es_confirmation_mail_subject' => array( 'default' => $confirmation_email_subject, 'old_option' => 'ig_es_confirmsubject' ),
794
- 'ig_es_confirmation_mail_content' => array( 'default' => $confirmation_email_content, 'old_option' => 'ig_es_confirmcontent' ),
795
- 'ig_es_enable_welcome_email' => array( 'default' => 'yes', 'old_option' => 'ig_es_welcomeemail', 'action' => 'convert_space_to_underscore' ),
796
- 'ig_es_welcome_email_subject' => array( 'default' => $welcome_email_subject, 'old_option' => 'ig_es_welcomesubject' ),
797
- 'ig_es_welcome_email_content' => array( 'default' => $welcome_email_content, 'old_option' => 'ig_es_welcomecontent' ),
798
- 'ig_es_enable_cron_admin_email' => array( 'default' => 'yes', 'old_option' => 'ig_es_enable_cron_adminmail' ),
799
- 'ig_es_enable_summary_automation' => array( 'default' => 'yes', 'old_option' => 'ig_es_enable_summary_automation' ),
800
- 'ig_es_run_cron_on' => array( 'default' => 'monday', 'old_option' => 'ig_es_run_cron_on' ),
801
- 'ig_es_run_cron_time' => array( 'default' => '4pm', 'old_option' => 'ig_es_run_cron_time' ),
802
- 'ig_es_cron_admin_email' => array( 'default' => $cron_admin_email, 'old_option' => 'ig_es_cron_adminmail' ),
803
- 'ig_es_cronurl' => array( 'default' => $cronurl, 'old_option' => 'ig_es_cronurl' ),
804
- 'ig_es_hourly_email_send_limit' => array( 'default' => 300, 'old_option' => 'ig_es_cron_mailcount' ),
805
- 'ig_es_sent_report_subject' => array( 'default' => 'Your email has been sent', 'old_option' => 'ig_es_sentreport_subject' ),
806
- 'ig_es_sent_report_content' => array( 'default' => $report, 'old_option' => 'ig_es_sentreport' ),
807
- 'ig_es_unsubscribe_link' => array( 'default' => $unsublink, 'old_option' => 'ig_es_unsublink' ),
808
- 'ig_es_optin_link' => array( 'default' => $optinlink, 'old_option' => 'ig_es_optinlink' ),
809
- 'ig_es_unsubscribe_link_content' => array( 'default' => $unsubscribe_link_content, 'old_option' => 'ig_es_unsubcontent' ),
810
- 'ig_es_email_type' => array( 'default' => 'wp_html_mail', 'old_option' => 'ig_es_emailtype', 'action' => 'convert_space_to_underscore' ),
811
- 'ig_es_notify_admin' => array( 'default' => 'yes', 'old_option' => 'ig_es_notifyadmin', 'action' => 'convert_space_to_underscore' ),
812
- 'ig_es_optin_type' => array( 'default' => 'double_opt_in', 'old_option' => 'ig_es_optintype', 'action' => 'convert_space_to_underscore' ),
813
- 'ig_es_subscription_error_messsage' => array( 'default' => $subscription_error_message, 'old_option' => 'ig_es_suberror' ),
814
- 'ig_es_subscription_success_message' => array( 'default' => 'You have been successfully subscribed.', 'old_option' => 'ig_es_successmsg' ),
815
- 'ig_es_unsubscribe_error_message' => array( 'default' => $unsubscribe_error_message, 'old_option' => 'ig_es_unsuberror' ),
816
- 'ig_es_unsubscribe_success_message' => array( 'default' => $unsubscribe_message, 'old_option' => 'ig_es_unsubtext' ),
817
- 'ig_es_post_image_size' => array( 'default' => 'thumbnail', 'old_option' => 'ig_es_post_image_size' ),
818
- 'ig_es_db_version' => array( 'default' => $latest_db_version, 'old_option' => 'current_sa_email_subscribers_db_version' ),
819
- 'ig_es_current_version_date_details' => array( 'default' => '', 'old_option' => '' ),
820
- 'ig_es_enable_captcha' => array( 'default' => '', 'old_option' => '' ),
821
- 'ig_es_roles_and_capabilities' => array( 'default' => '', 'old_option' => 'ig_es_rolesandcapabilities' ),
822
- 'ig_es_sample_data_imported' => array( 'default' => 'no', 'old_option' => '' ),
823
- 'ig_es_default_subscriber_imported' => array( 'default' => 'no', 'old_option' => '' ),
824
- 'ig_es_set_widget' => array( 'default' => '', 'old_option' => '' ),
825
- 'ig_es_sync_wp_users' => array( 'default' => array(), 'old_option' => '' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
826
  'ig_es_blocked_domains' => array( 'default' => 'mail.ru' ),
827
  'ig_es_disable_wp_cron' => array( 'default' => 'no' ),
828
  'ig_es_track_email_opens' => array( 'default' => 'yes' ),
829
  'ig_es_show_opt_in_consent' => array( 'default' => 'yes' ),
830
  'ig_es_opt_in_consent_text' => array( 'default' => 'Subscribe to our email updates as well.' ),
831
- 'ig_es_installed_on' => array( 'default' => ig_get_current_date_time(), 'old_option' => '' ),
832
- 'ig_es_form_submission_success_message' => array( 'default' => __( 'Your subscription was successful! Kindly check your mailbox and confirm your subscription. If you don\'t see the email within a few minutes, check the spam/junk folder.', 'email-subscribers' ), 'old_option' => '' ),
 
 
 
 
 
 
833
  'ig_es_db_update_history' => array( 'default' => $ig_es_db_update_history ),
834
  'ig_es_email_sent_data' => array( 'default' => array() ),
835
- 'ig_es_mailer_settings' => array( 'default' => array( 'mailer' => 'wpmail' ), 'old_option' => '' ),
836
- 'ig_es_user_roles' => array( 'default' => self::get_default_permissions(), 'old_option' => '' ),
837
- 'ig_es_cron_interval' => array( 'default' => IG_ES_CRON_INTERVAL, 'old_option' => '' ),
838
- 'ig_es_max_email_send_at_once' => array( 'default' => IG_ES_MAX_EMAIL_SEND_AT_ONCE, 'old_option' => '' ),
839
- 'ig_es_test_mailbox_user' => array( 'default' => ES_Common::generate_test_mailbox_user(), 'old_option' => '' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
840
  );
841
 
842
  return $options;
@@ -1320,7 +1453,7 @@ if ( ! class_exists( 'ES_Install' ) ) {
1320
  */
1321
  private static function get_schema( $collate = '' ) {
1322
 
1323
- $tables = self::get_ig_es_400_schema( $collate );
1324
  $tables .= self::get_ig_es_420_schema( $collate );
1325
  $tables .= self::get_ig_es_421_schema( $collate );
1326
  $tables .= self::get_ig_es_424_schema( $collate );
@@ -1338,7 +1471,7 @@ if ( ! class_exists( 'ES_Install' ) ) {
1338
  * @since 4.3.2
1339
  */
1340
  public static function load_templates( $force = false ) {
1341
- //TODO :: Add template with custom post type
1342
  global $wpdb;
1343
 
1344
  $plan = 'lite';
@@ -1384,8 +1517,8 @@ if ( ! class_exists( 'ES_Install' ) ) {
1384
  'post_name' => $slug,
1385
  'meta_input' => array(
1386
  'es_template_type' => $template['es_email_type'],
1387
- 'es_custom_css' => $template['es_custom_css']
1388
- )
1389
  );
1390
  // Insert the post into the database.
1391
  $last_inserted_id = wp_insert_post( $es_post );
@@ -1425,7 +1558,7 @@ if ( ! class_exists( 'ES_Install' ) ) {
1425
  'post_mime_type' => $wp_filetype['type'],
1426
  'post_title' => sanitize_file_name( $filename ),
1427
  'post_content' => '',
1428
- 'post_status' => 'inherit'
1429
  );
1430
  $attach_id = wp_insert_attachment( $attachment, $file, $post_id );
1431
  require_once ABSPATH . 'wp-admin/includes/image.php';
@@ -1482,27 +1615,27 @@ if ( ! class_exists( 'ES_Install' ) ) {
1482
  public static function get_default_permissions() {
1483
 
1484
  $campaigns_permission = array(
1485
- 'administrator' => 'yes'
1486
  );
1487
 
1488
  $reports_permission = array(
1489
- 'administrator' => 'yes'
1490
  );
1491
 
1492
  $sequence_permission = array(
1493
- 'administrator' => 'yes'
1494
  );
1495
 
1496
  $audience_permission = array(
1497
- 'administrator' => 'yes'
1498
  );
1499
 
1500
  $forms_permission = array(
1501
- 'administrator' => 'yes'
1502
  );
1503
 
1504
  $workflows_permission = array(
1505
- 'administrator' => 'yes'
1506
  );
1507
 
1508
  $es_roles_default_permission['campaigns'] = $campaigns_permission;
21
  *
22
  * @since 4.2.0
23
  * @var array
 
24
  */
25
  public static $logger_context = array(
26
+ 'source' => 'ig_es_db_updates',
27
  );
28
 
29
  /**
31
  *
32
  * @since 4.0.0
33
  * @var array
 
34
  */
35
  private static $db_updates = array(
36
 
37
+ '3.2.0' => array(
38
  'ig_es_update_320_add_sync_option',
39
+ 'ig_es_update_320_db_version',
40
  ),
41
 
42
+ '3.2.7' => array(
43
  'ig_es_update_327_change_email_type',
44
+ 'ig_es_update_327_db_version',
45
  ),
46
 
47
+ '3.3.0' => array(
48
  'ig_es_update_330_import_options',
49
+ 'ig_es_update_330_db_version',
50
  ),
51
 
52
+ '3.3.6' => array(
53
  'ig_es_update_336_add_template_slug',
54
+ 'ig_es_update_336_db_version',
55
  ),
56
 
57
+ '3.4.0' => array(
58
  'ig_es_update_340_migrate_templates_to_cpt',
59
  'ig_es_update_340_migrate_keywords',
60
+ 'ig_es_update_340_db_version',
61
  ),
62
 
63
  '3.5.16' => array(
64
  'ig_es_update_3516_create_subscribers_ips_table',
65
+ 'ig_es_update_3516_db_version',
66
  ),
67
 
68
 
69
+ '4.0.0' => array(
70
  /**
71
  * - Create Tables
72
  * - Import Options
86
  'ig_es_update_400_migrate_post_notifications',
87
  'ig_es_update_400_migrate_notifications',
88
  'ig_es_update_400_migrate_group_selectors_forms',
89
+ 'ig_es_update_400_db_version',
90
  ),
91
 
92
+ '4.0.1' => array(
93
  'ig_es_update_401_migrate_newsletters',
94
+ 'ig_es_update_401_db_version',
95
  ),
96
 
97
+ '4.0.2' => array(
98
  'ig_es_update_402_migrate_post_notification_es_template_type',
99
+ 'ig_es_update_402_db_version',
100
  ),
101
 
102
+ '4.0.3' => array(
103
  'ig_es_update_403_alter_campaigns_table',
104
  'ig_es_update_403_alter_mailing_queue_table',
105
+ 'ig_es_update_403_db_version',
106
  ),
107
 
108
+ '4.0.5' => array(
109
  'ig_es_update_405_alter_forms_table',
110
  'ig_es_update_405_alter_lists_table',
111
  'ig_es_update_405_migrate_widgets',
112
+ 'ig_es_update_405_db_version',
113
  ),
114
 
115
  '4.0.10' => array(
116
+ 'ig_es_update_4010_db_version',
117
  ),
118
 
119
  '4.0.11' => array(
120
  'ig_es_update_4011_migrate_newsletter_es_template_type',
121
  'ig_es_update_4011_update_campaign_id_in_mailing_queue',
122
+ 'ig_es_update_4011_db_version',
123
  ),
124
 
125
  '4.0.15' => array(
127
  'ig_es_update_4015_db_version',
128
  ),
129
 
130
+ '4.1.1' => array(
131
  'ig_es_update_411_alter_contacts_table',
132
+ 'ig_es_update_411_db_version',
133
  ),
134
 
135
+ '4.1.7' => array(
136
  'ig_es_update_417_alter_campaigns_table',
137
  'ig_es_update_417_alter_mailing_queue_table',
138
+ 'ig_es_update_417_db_version',
139
  ),
140
 
141
  '4.1.13' => array(
142
  'ig_es_update_4113_migrate_categories_in_campaigns_table',
143
  'ig_es_update_4113_create_files',
144
+ 'ig_es_update_4113_db_version',
145
  ),
146
  '4.1.15' => array(
147
  'ig_es_update_4115_add_form_submission_option',
148
  'ig_es_update_4115_migrate_db_update_history',
149
+ 'ig_es_update_4115_db_version',
150
  ),
151
 
152
+ '4.2.0' => array(
153
  'ig_es_update_420_alter_campaigns_table',
154
  'ig_es_update_420_create_tables',
155
  'ig_es_update_420_migrate_mailer_options',
156
+ 'ig_es_update_420_db_version',
157
  ),
158
 
159
+ '4.2.1' => array(
160
  'ig_es_update_421_drop_tables',
161
  'ig_es_update_421_create_tables',
162
+ 'ig_es_update_421_db_version',
163
  ),
164
 
165
+ '4.2.4' => array(
166
  'ig_es_update_424_drop_tables',
167
  'ig_es_update_424_create_tables',
168
+ 'ig_es_update_424_db_version',
169
  ),
170
 
171
+ '4.3.0' => array(
172
  'ig_es_update_430_alter_campaigns_table',
173
+ 'ig_es_update_430_db_version',
174
  ),
175
 
176
+ '4.3.1' => array(
177
  'ig_es_update_431_set_default_permissions',
178
  'ig_es_update_431_permanently_delete_lists',
179
  'ig_es_update_431_permanently_delete_forms',
180
  'ig_es_update_431_disable_autoload_options',
181
+ 'ig_es_update_431_db_version',
182
  ),
183
 
184
+ '4.3.2' => array(
185
  'ig_es_update_432_import_bfcm_templates',
186
+ 'ig_es_update_432_db_version',
187
  ),
188
 
189
+ '4.3.4' => array(
190
  'ig_es_update_434_permanently_delete_campaigns',
191
+ 'ig_es_update_434_db_version',
192
  ),
193
 
194
+ '4.4.1' => array(
195
  'ig_es_update_441_create_tables',
196
  'ig_es_update_441_migrate_audience_sync_settings',
197
+ 'ig_es_update_441_db_version',
198
  ),
199
 
200
+ '4.4.2' => array(
201
  'ig_es_update_442_set_workflows_default_permission',
202
+ 'ig_es_update_442_db_version',
203
  ),
204
 
205
+ '4.4.9' => array(
206
  'ig_es_update_449_create_tables',
207
+ 'ig_es_update_449_db_version',
208
  ),
209
 
210
  '4.4.10' => array(
211
  'ig_es_update_4410_load_templates',
212
+ 'ig_es_update_4410_db_version',
213
  ),
214
 
215
+ '4.5.0' => array(
216
  'ig_es_update_450_alter_actions_table',
217
+ 'ig_es_update_450_db_version',
218
  ),
219
 
220
+ '4.5.7' => array(
221
  'ig_es_update_457_alter_list_table',
222
  'ig_es_update_457_add_list_hash',
223
  'ig_es_update_457_db_version',
224
  ),
225
 
226
+ '4.6.3' => array(
227
  'ig_es_update_463_alter_contacts_table',
228
  'ig_es_migrate_ip_from_list_contacts_to_contacts_table',
229
  'ig_es_update_463_db_version',
230
  ),
231
 
232
+ '4.6.5' => array(
233
  'ig_es_update_465_create_tables',
234
  'ig_es_update_465_db_version',
235
  ),
236
+ '4.6.6' => array(
237
  'ig_es_update_466_create_temp_import_table',
238
  'ig_es_update_466_db_version',
239
  ),
240
+ '4.6.7' => array(
241
  'ig_es_update_467_alter_contacts_table',
242
  'ig_es_add_country_code_to_contacts_table',
243
  'ig_es_update_467_db_version',
244
  ),
245
+ '4.6.8' => array(
246
  'ig_es_update_468_create_unsubscribe_feedback_table',
247
  'ig_es_update_468_db_version',
248
  ),
249
+ '4.6.9' => array(
250
  'ig_es_update_469_alter_wc_guests_table',
251
  'ig_es_update_469_db_version',
252
  ),
254
  'ig_es_migrate_4613_sequence_list_settings_into_campaign_rules',
255
  'ig_es_update_4613_db_version',
256
  ),
257
+ '4.7.8' => array(
258
  'ig_es_add_index_to_list_contacts_table',
259
  'ig_es_update_478_db_version',
260
  ),
261
+ '4.7.9' => array(
262
  'ig_es_add_primay_key_to_actions_table',
263
  'ig_es_update_479_db_version',
264
  ),
322
 
323
  self::update( true );
324
 
325
+ // ES_Admin_Notices::add_notice( 'update' );
326
  }
327
 
328
  if ( ! empty( $_GET['force_update_ig_es'] ) ) {
329
  check_admin_referer( 'ig_es_force_db_update', 'ig_es_force_db_update_nonce' );
330
  self::update();
331
+ // ES_Admin_Notices::add_notice( 'update' );
332
  wp_safe_redirect( admin_url( 'admin.php?page=es_settings' ) );
333
  exit;
334
  }
344
  // Create Files
345
  self::create_files();
346
 
 
347
  if ( ! is_blog_installed() ) {
348
  self::$logger->error( 'Blog is not installed.', self::$logger_context );
349
 
421
  *
422
  * If we found 'current_sa_email_subscribers_db_version' option, which means it's a
423
  * migration from ES 3.5.x
 
424
  */
425
  return is_null( get_option( 'ig_es_db_version', null ) ) && is_null( get_option( 'current_sa_email_subscribers_db_version', null ) ) && is_null( get_option( 'email-subscribers', null ) );
426
  }
471
  self::update();
472
  } else {
473
  self::$logger->info( 'Show update notice.', self::$logger_context );
474
+ // ES_Admin_Notices::add_notice( 'update' );
475
  }
476
  } else {
477
  self::$logger->info( 'Database is upto date' );
584
  foreach ( $batch as $key => $value ) {
585
 
586
  $is_value_exists = true;
587
+ // $task_transient = $value . '_processed';
588
  $ig_es_update_processed_tasks = get_option( 'ig_es_update_processed_tasks', array() );
589
  $task = false; // By default it's set to false
590
 
608
 
609
  unset( $batch[ $key ] );
610
  }
 
611
  }
612
 
613
  update_option( 'ig_es_update_tasks_to_process', $batch );
614
  }
615
 
616
+ // Delete update transient
617
  delete_transient( 'ig_es_updating' );
618
  }
619
 
708
  $sender_details['name'] = $blog_name;
709
  $sender_details['email'] = $admin_email;
710
 
711
+ // check if installed WP Mail SMTP
712
  if ( in_array( 'wp-mail-smtp/wp_mail_smtp.php', $active_plugins ) ) {
713
  $wp_mail_smtp_settings = get_option( 'wp_mail_smtp', array() );
714
 
740
  $latest_db_version = self::get_latest_db_version_to_update();
741
 
742
  $ig_es_db_update_history = array(
743
+ $latest_db_version => ig_get_current_date_time(),
744
  );
745
 
746
  $sender_details = self::get_sender_details();
752
  $guid = ES_Common::generate_guid( 6 );
753
  $cronurl = $home_url . '?es=cron&guid=' . $guid;
754
 
755
+ $report = '';
756
  $report .= "Hi Admin,\n\n";
757
  $report .= "Email has been sent successfully to {{COUNT}} email(s). Please find the details below:\n\n";
758
  $report .= "Unique ID: {{UNIQUE}}\n";
761
  $report .= "For more information, login to your dashboard and go to Reports menu in Email Subscribers.\n\n";
762
  $report .= 'Thank You.';
763
 
 
764
  $new_contact_email_subject = 'One more contact joins our tribe!';
765
  $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...";
766
 
779
  $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";
780
 
781
  $options = array(
782
+ 'ig_es_from_name' => array(
783
+ 'default' => $sender_details['name'],
784
+ 'old_option' => 'ig_es_fromname',
785
+ ),
786
+ 'ig_es_from_email' => array(
787
+ 'default' => $sender_details['email'],
788
+ 'old_option' => 'ig_es_fromemail',
789
+ ),
790
+ 'ig_es_admin_new_contact_email_subject' => array(
791
+ 'default' => $new_contact_email_subject,
792
+ 'old_option' => 'ig_es_admin_new_sub_subject',
793
+ ),
794
+ 'ig_es_admin_new_contact_email_content' => array(
795
+ 'default' => $new_contact_email_content,
796
+ 'old_option' => 'ig_es_admin_new_sub_content',
797
+ ),
798
+ 'ig_es_admin_emails' => array(
799
+ 'default' => $admin_email,
800
+ 'old_option' => 'ig_es_adminemail',
801
+ ),
802
+ 'ig_es_confirmation_mail_subject' => array(
803
+ 'default' => $confirmation_email_subject,
804
+ 'old_option' => 'ig_es_confirmsubject',
805
+ ),
806
+ 'ig_es_confirmation_mail_content' => array(
807
+ 'default' => $confirmation_email_content,
808
+ 'old_option' => 'ig_es_confirmcontent',
809
+ ),
810
+ 'ig_es_enable_welcome_email' => array(
811
+ 'default' => 'yes',
812
+ 'old_option' => 'ig_es_welcomeemail',
813
+ 'action' => 'convert_space_to_underscore',
814
+ ),
815
+ 'ig_es_welcome_email_subject' => array(
816
+ 'default' => $welcome_email_subject,
817
+ 'old_option' => 'ig_es_welcomesubject',
818
+ ),
819
+ 'ig_es_welcome_email_content' => array(
820
+ 'default' => $welcome_email_content,
821
+ 'old_option' => 'ig_es_welcomecontent',
822
+ ),
823
+ 'ig_es_enable_cron_admin_email' => array(
824
+ 'default' => 'yes',
825
+ 'old_option' => 'ig_es_enable_cron_adminmail',
826
+ ),
827
+ 'ig_es_enable_summary_automation' => array(
828
+ 'default' => 'yes',
829
+ 'old_option' => 'ig_es_enable_summary_automation',
830
+ ),
831
+ 'ig_es_run_cron_on' => array(
832
+ 'default' => 'monday',
833
+ 'old_option' => 'ig_es_run_cron_on',
834
+ ),
835
+ 'ig_es_run_cron_time' => array(
836
+ 'default' => '4pm',
837
+ 'old_option' => 'ig_es_run_cron_time',
838
+ ),
839
+ 'ig_es_cron_admin_email' => array(
840
+ 'default' => $cron_admin_email,
841
+ 'old_option' => 'ig_es_cron_adminmail',
842
+ ),
843
+ 'ig_es_cronurl' => array(
844
+ 'default' => $cronurl,
845
+ 'old_option' => 'ig_es_cronurl',
846
+ ),
847
+ 'ig_es_hourly_email_send_limit' => array(
848
+ 'default' => 300,
849
+ 'old_option' => 'ig_es_cron_mailcount',
850
+ ),
851
+ 'ig_es_sent_report_subject' => array(
852
+ 'default' => 'Your email has been sent',
853
+ 'old_option' => 'ig_es_sentreport_subject',
854
+ ),
855
+ 'ig_es_sent_report_content' => array(
856
+ 'default' => $report,
857
+ 'old_option' => 'ig_es_sentreport',
858
+ ),
859
+ 'ig_es_unsubscribe_link' => array(
860
+ 'default' => $unsublink,
861
+ 'old_option' => 'ig_es_unsublink',
862
+ ),
863
+ 'ig_es_optin_link' => array(
864
+ 'default' => $optinlink,
865
+ 'old_option' => 'ig_es_optinlink',
866
+ ),
867
+ 'ig_es_unsubscribe_link_content' => array(
868
+ 'default' => $unsubscribe_link_content,
869
+ 'old_option' => 'ig_es_unsubcontent',
870
+ ),
871
+ 'ig_es_email_type' => array(
872
+ 'default' => 'wp_html_mail',
873
+ 'old_option' => 'ig_es_emailtype',
874
+ 'action' => 'convert_space_to_underscore',
875
+ ),
876
+ 'ig_es_notify_admin' => array(
877
+ 'default' => 'yes',
878
+ 'old_option' => 'ig_es_notifyadmin',
879
+ 'action' => 'convert_space_to_underscore',
880
+ ),
881
+ 'ig_es_optin_type' => array(
882
+ 'default' => 'double_opt_in',
883
+ 'old_option' => 'ig_es_optintype',
884
+ 'action' => 'convert_space_to_underscore',
885
+ ),
886
+ 'ig_es_subscription_error_messsage' => array(
887
+ 'default' => $subscription_error_message,
888
+ 'old_option' => 'ig_es_suberror',
889
+ ),
890
+ 'ig_es_subscription_success_message' => array(
891
+ 'default' => 'You have been successfully subscribed.',
892
+ 'old_option' => 'ig_es_successmsg',
893
+ ),
894
+ 'ig_es_unsubscribe_error_message' => array(
895
+ 'default' => $unsubscribe_error_message,
896
+ 'old_option' => 'ig_es_unsuberror',
897
+ ),
898
+ 'ig_es_unsubscribe_success_message' => array(
899
+ 'default' => $unsubscribe_message,
900
+ 'old_option' => 'ig_es_unsubtext',
901
+ ),
902
+ 'ig_es_post_image_size' => array(
903
+ 'default' => 'thumbnail',
904
+ 'old_option' => 'ig_es_post_image_size',
905
+ ),
906
+ 'ig_es_db_version' => array(
907
+ 'default' => $latest_db_version,
908
+ 'old_option' => 'current_sa_email_subscribers_db_version',
909
+ ),
910
+ 'ig_es_current_version_date_details' => array(
911
+ 'default' => '',
912
+ 'old_option' => '',
913
+ ),
914
+ 'ig_es_enable_captcha' => array(
915
+ 'default' => '',
916
+ 'old_option' => '',
917
+ ),
918
+ 'ig_es_roles_and_capabilities' => array(
919
+ 'default' => '',
920
+ 'old_option' => 'ig_es_rolesandcapabilities',
921
+ ),
922
+ 'ig_es_sample_data_imported' => array(
923
+ 'default' => 'no',
924
+ 'old_option' => '',
925
+ ),
926
+ 'ig_es_default_subscriber_imported' => array(
927
+ 'default' => 'no',
928
+ 'old_option' => '',
929
+ ),
930
+ 'ig_es_set_widget' => array(
931
+ 'default' => '',
932
+ 'old_option' => '',
933
+ ),
934
+ 'ig_es_sync_wp_users' => array(
935
+ 'default' => array(),
936
+ 'old_option' => '',
937
+ ),
938
  'ig_es_blocked_domains' => array( 'default' => 'mail.ru' ),
939
  'ig_es_disable_wp_cron' => array( 'default' => 'no' ),
940
  'ig_es_track_email_opens' => array( 'default' => 'yes' ),
941
  'ig_es_show_opt_in_consent' => array( 'default' => 'yes' ),
942
  'ig_es_opt_in_consent_text' => array( 'default' => 'Subscribe to our email updates as well.' ),
943
+ 'ig_es_installed_on' => array(
944
+ 'default' => ig_get_current_date_time(),
945
+ 'old_option' => '',
946
+ ),
947
+ 'ig_es_form_submission_success_message' => array(
948
+ 'default' => __( 'Your subscription was successful! Kindly check your mailbox and confirm your subscription. If you don\'t see the email within a few minutes, check the spam/junk folder.', 'email-subscribers' ),
949
+ 'old_option' => '',
950
+ ),
951
  'ig_es_db_update_history' => array( 'default' => $ig_es_db_update_history ),
952
  'ig_es_email_sent_data' => array( 'default' => array() ),
953
+ 'ig_es_mailer_settings' => array(
954
+ 'default' => array( 'mailer' => 'wpmail' ),
955
+ 'old_option' => '',
956
+ ),
957
+ 'ig_es_user_roles' => array(
958
+ 'default' => self::get_default_permissions(),
959
+ 'old_option' => '',
960
+ ),
961
+ 'ig_es_cron_interval' => array(
962
+ 'default' => IG_ES_CRON_INTERVAL,
963
+ 'old_option' => '',
964
+ ),
965
+ 'ig_es_max_email_send_at_once' => array(
966
+ 'default' => IG_ES_MAX_EMAIL_SEND_AT_ONCE,
967
+ 'old_option' => '',
968
+ ),
969
+ 'ig_es_test_mailbox_user' => array(
970
+ 'default' => ES_Common::generate_test_mailbox_user(),
971
+ 'old_option' => '',
972
+ ),
973
  );
974
 
975
  return $options;
1453
  */
1454
  private static function get_schema( $collate = '' ) {
1455
 
1456
+ $tables = self::get_ig_es_400_schema( $collate );
1457
  $tables .= self::get_ig_es_420_schema( $collate );
1458
  $tables .= self::get_ig_es_421_schema( $collate );
1459
  $tables .= self::get_ig_es_424_schema( $collate );
1471
  * @since 4.3.2
1472
  */
1473
  public static function load_templates( $force = false ) {
1474
+ // TODO :: Add template with custom post type
1475
  global $wpdb;
1476
 
1477
  $plan = 'lite';
1517
  'post_name' => $slug,
1518
  'meta_input' => array(
1519
  'es_template_type' => $template['es_email_type'],
1520
+ 'es_custom_css' => $template['es_custom_css'],
1521
+ ),
1522
  );
1523
  // Insert the post into the database.
1524
  $last_inserted_id = wp_insert_post( $es_post );
1558
  'post_mime_type' => $wp_filetype['type'],
1559
  'post_title' => sanitize_file_name( $filename ),
1560
  'post_content' => '',
1561
+ 'post_status' => 'inherit',
1562
  );
1563
  $attach_id = wp_insert_attachment( $attachment, $file, $post_id );
1564
  require_once ABSPATH . 'wp-admin/includes/image.php';
1615
  public static function get_default_permissions() {
1616
 
1617
  $campaigns_permission = array(
1618
+ 'administrator' => 'yes',
1619
  );
1620
 
1621
  $reports_permission = array(
1622
+ 'administrator' => 'yes',
1623
  );
1624
 
1625
  $sequence_permission = array(
1626
+ 'administrator' => 'yes',
1627
  );
1628
 
1629
  $audience_permission = array(
1630
+ 'administrator' => 'yes',
1631
  );
1632
 
1633
  $forms_permission = array(
1634
+ 'administrator' => 'yes',
1635
  );
1636
 
1637
  $workflows_permission = array(
1638
+ 'administrator' => 'yes',
1639
  );
1640
 
1641
  $es_roles_default_permission['campaigns'] = $campaigns_permission;
lite/includes/class-ig-logger.php CHANGED
@@ -22,7 +22,7 @@ if ( ! class_exists( 'IG_Logger' ) ) {
22
 
23
  if ( is_object( $handler ) && is_array( $implements ) && in_array( 'IG_Log_Handler_Interface', $implements, true ) ) {
24
  $register_handlers[] = $handler;
25
- }
26
  }
27
  }
28
 
@@ -85,7 +85,7 @@ if ( ! class_exists( 'IG_Logger' ) ) {
85
  * 'info': Informational messages.
86
  * 'debug': Debug-level messages.
87
  * @param string $message Log message.
88
- * @param array $context Optional. Additional information for log handlers.
89
  */
90
  public function log( $level, $message, $context = array() ) {
91
 
@@ -107,7 +107,7 @@ if ( ! class_exists( 'IG_Logger' ) ) {
107
  * @see IG_Logger::log
108
  *
109
  * @param string $message Message to log.
110
- * @param array $context Log context.
111
  */
112
  public function emergency( $message, $context = array() ) {
113
  $this->log( IG_Log_Levels::EMERGENCY, $message, $context );
@@ -122,7 +122,7 @@ if ( ! class_exists( 'IG_Logger' ) ) {
122
  * @see IG_Logger::log
123
  *
124
  * @param string $message Message to log.
125
- * @param array $context Log context.
126
  */
127
  public function alert( $message, $context = array() ) {
128
  $this->log( IG_Log_Levels::ALERT, $message, $context );
@@ -137,7 +137,7 @@ if ( ! class_exists( 'IG_Logger' ) ) {
137
  * @see IG_Logger::log
138
  *
139
  * @param string $message Message to log.
140
- * @param array $context Log context.
141
  */
142
  public function critical( $message, $context = array() ) {
143
  $this->log( IG_Log_Levels::CRITICAL, $message, $context );
@@ -152,7 +152,7 @@ if ( ! class_exists( 'IG_Logger' ) ) {
152
  * @see IG_Logger::log
153
  *
154
  * @param string $message Message to log.
155
- * @param array $context Log context.
156
  */
157
  public function error( $message, $context = array() ) {
158
  $this->log( IG_Log_Levels::ERROR, $message, $context );
@@ -169,7 +169,7 @@ if ( ! class_exists( 'IG_Logger' ) ) {
169
  * @see IG_Logger::log
170
  *
171
  * @param string $message Message to log.
172
- * @param array $context Log context.
173
  */
174
  public function warning( $message, $context = array() ) {
175
  $this->log( IG_Log_Levels::WARNING, $message, $context );
@@ -183,7 +183,7 @@ if ( ! class_exists( 'IG_Logger' ) ) {
183
  * @see IG_Logger::log
184
  *
185
  * @param string $message Message to log.
186
- * @param array $context Log context.
187
  */
188
  public function notice( $message, $context = array() ) {
189
  $this->log( IG_Log_Levels::NOTICE, $message, $context );
@@ -198,7 +198,7 @@ if ( ! class_exists( 'IG_Logger' ) ) {
198
  * @see IG_Logger::log
199
  *
200
  * @param string $message Message to log.
201
- * @param array $context Log context.
202
  */
203
  public function info( $message, $context = array() ) {
204
  $this->log( IG_Log_Levels::INFO, $message, $context );
@@ -242,7 +242,7 @@ if ( ! class_exists( 'IG_Logger' ) ) {
242
  * @see IG_Logger::log
243
  *
244
  * @param string $message Message to log.
245
- * @param array $context Log context.
246
  */
247
  public function debug( $message, $context = array() ) {
248
  $this->log( IG_Log_Levels::DEBUG, $message, $context );
22
 
23
  if ( is_object( $handler ) && is_array( $implements ) && in_array( 'IG_Log_Handler_Interface', $implements, true ) ) {
24
  $register_handlers[] = $handler;
25
+ }
26
  }
27
  }
28
 
85
  * 'info': Informational messages.
86
  * 'debug': Debug-level messages.
87
  * @param string $message Log message.
88
+ * @param array $context Optional. Additional information for log handlers.
89
  */
90
  public function log( $level, $message, $context = array() ) {
91
 
107
  * @see IG_Logger::log
108
  *
109
  * @param string $message Message to log.
110
+ * @param array $context Log context.
111
  */
112
  public function emergency( $message, $context = array() ) {
113
  $this->log( IG_Log_Levels::EMERGENCY, $message, $context );
122
  * @see IG_Logger::log
123
  *
124
  * @param string $message Message to log.
125
+ * @param array $context Log context.
126
  */
127
  public function alert( $message, $context = array() ) {
128
  $this->log( IG_Log_Levels::ALERT, $message, $context );
137
  * @see IG_Logger::log
138
  *
139
  * @param string $message Message to log.
140
+ * @param array $context Log context.
141
  */
142
  public function critical( $message, $context = array() ) {
143
  $this->log( IG_Log_Levels::CRITICAL, $message, $context );
152
  * @see IG_Logger::log
153
  *
154
  * @param string $message Message to log.
155
+ * @param array $context Log context.
156
  */
157
  public function error( $message, $context = array() ) {
158
  $this->log( IG_Log_Levels::ERROR, $message, $context );
169
  * @see IG_Logger::log
170
  *
171
  * @param string $message Message to log.
172
+ * @param array $context Log context.
173
  */
174
  public function warning( $message, $context = array() ) {
175
  $this->log( IG_Log_Levels::WARNING, $message, $context );
183
  * @see IG_Logger::log
184
  *
185
  * @param string $message Message to log.
186
+ * @param array $context Log context.
187
  */
188
  public function notice( $message, $context = array() ) {
189
  $this->log( IG_Log_Levels::NOTICE, $message, $context );
198
  * @see IG_Logger::log
199
  *
200
  * @param string $message Message to log.
201
+ * @param array $context Log context.
202
  */
203
  public function info( $message, $context = array() ) {
204
  $this->log( IG_Log_Levels::INFO, $message, $context );
242
  * @see IG_Logger::log
243
  *
244
  * @param string $message Message to log.
245
+ * @param array $context Log context.
246
  */
247
  public function debug( $message, $context = array() ) {
248
  $this->log( IG_Log_Levels::DEBUG, $message, $context );
lite/includes/classes/class-es-actions.php CHANGED
@@ -46,7 +46,6 @@ if ( ! class_exists( 'ES_Actions' ) ) {
46
  * Init Actions
47
  *
48
  * @since 4.2.0
49
- *
50
  */
51
  public function init() {
52
  add_action( 'ig_es_contact_subscribe', array( &$this, 'subscribe' ), 10, 2 );
@@ -309,7 +308,7 @@ if ( ! class_exists( 'ES_Actions' ) ) {
309
  }
310
 
311
  /**
312
- * Method to update campaign viewed/opened_at status
313
  *
314
  * @param int $conact_id
315
  * @param int $campaign_id
@@ -327,10 +326,10 @@ if ( ! class_exists( 'ES_Actions' ) ) {
327
  }
328
 
329
  $current_date = ig_get_current_date_time();
330
- $sql = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}ig_sending_queue SET opened_at = %s, opened = %d WHERE contact_id = %d AND campaign_id = %d AND mailing_queue_id = %d", $current_date, 1, $conact_id, $campaign_id, $message_id ) );
331
 
332
  return $sql;
333
-
334
  }
335
 
336
  /**
46
  * Init Actions
47
  *
48
  * @since 4.2.0
 
49
  */
50
  public function init() {
51
  add_action( 'ig_es_contact_subscribe', array( &$this, 'subscribe' ), 10, 2 );
308
  }
309
 
310
  /**
311
+ * Method to update campaign viewed/opened_at status
312
  *
313
  * @param int $conact_id
314
  * @param int $campaign_id
326
  }
327
 
328
  $current_date = ig_get_current_date_time();
329
+ $sql = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}ig_sending_queue SET opened_at = %s, opened = %d WHERE contact_id = %d AND campaign_id = %d AND mailing_queue_id = %d", $current_date, 1, $conact_id, $campaign_id, $message_id ) );
330
 
331
  return $sql;
332
+
333
  }
334
 
335
  /**
lite/includes/classes/class-es-admin-settings.php CHANGED
@@ -21,10 +21,10 @@ class ES_Admin_Settings {
21
 
22
  public function __construct() {
23
  add_filter( 'ig_es_registered_email_sending_settings', array( $this, 'show_cron_info' ) );
24
-
25
  // Start-IG-Code.
26
  // Add setting for plugin usage tracking
27
- add_filter( 'ig_es_registered_settings', array( $this, 'show_usage_tracking_optin_setting'), 30 );
28
  // End-IG-Code.
29
  }
30
 
@@ -45,22 +45,22 @@ class ES_Admin_Settings {
45
 
46
  $options = apply_filters( 'ig_es_before_save_settings', $options );
47
 
48
- $options['ig_es_disable_wp_cron'] = isset( $options['ig_es_disable_wp_cron'] ) ? $options['ig_es_disable_wp_cron'] : 'no';
49
- $options['ig_es_track_email_opens'] = isset( $options['ig_es_track_email_opens'] ) ? $options['ig_es_track_email_opens'] : 'no';
50
- $options['ig_es_enable_welcome_email'] = isset( $options['ig_es_enable_welcome_email'] ) ? $options['ig_es_enable_welcome_email'] : 'no';
51
- $options['ig_es_notify_admin'] = isset( $options['ig_es_notify_admin'] ) ? $options['ig_es_notify_admin'] : 'no';
52
- $options['ig_es_enable_cron_admin_email'] = isset( $options['ig_es_enable_cron_admin_email'] ) ? $options['ig_es_enable_cron_admin_email'] : 'no';
53
- $options['ig_es_delete_plugin_data'] = isset( $options['ig_es_delete_plugin_data'] ) ? $options['ig_es_delete_plugin_data'] : 'no';
54
- $options['ig_es_run_cron_on'] = isset( $options['ig_es_run_cron_on'] ) ? $options['ig_es_run_cron_on'] : 'monday';
55
- $options['ig_es_run_cron_time'] = isset( $options['ig_es_run_cron_time'] ) ? $options['ig_es_run_cron_time'] : '4pm';
56
  // Start-IG-Code.
57
  // Show option to enable/disable tracking if user isn't a premium user and trial is not valid i.e. has expired.
58
  if ( ! ES()->is_premium() && ! ES()->is_trial_valid() ) {
59
  $options['ig_es_allow_tracking'] = isset( $options['ig_es_allow_tracking'] ) ? $options['ig_es_allow_tracking'] : 'no';
60
  }
61
- $options['ig_es_powered_by'] = isset( $options['ig_es_powered_by'] ) ? $options['ig_es_powered_by'] : 'no';
62
  // End-IG-Code.
63
-
64
  $text_fields_to_sanitize = array(
65
  'ig_es_from_name',
66
  'ig_es_admin_emails',
@@ -122,7 +122,7 @@ class ES_Admin_Settings {
122
  ES_Common::show_message( $message, $status );
123
  }
124
  }
125
- $allowedtags = ig_es_allowed_html_tags_in_esc();
126
 
127
  ?>
128
 
@@ -155,7 +155,7 @@ class ES_Admin_Settings {
155
  'name' => __( 'Security', 'email-subscribers' ),
156
  ),
157
  );
158
- $es_settings_tabs = apply_filters('ig_es_settings_tabs', $es_settings_tabs );
159
  ?>
160
  <div id="es-settings-menu" class="w-1/5 pt-4 leading-normal text-gray-800 border-r border-gray-100">
161
  <div class="z-20 my-2 mt-0 bg-white shadow es-menu-list lg:block lg:my-0 lg:border-transparent lg:shadow-none lg:bg-transparent" style="top:6em;" id="menu-content">
@@ -220,7 +220,7 @@ class ES_Admin_Settings {
220
  'admin_email' => array(
221
  'id' => 'ig_es_admin_emails',
222
  'name' => __( 'Admin emails', 'email-subscribers' ),
223
- 'info' => __( 'Who should be notified about system events like "someone subscribed", "campaign sent" etc?', 'email-subscribers' ),
224
  'type' => 'text',
225
  'desc' => __( 'You can enter multiple email addresses - separate them with comma', 'email-subscribers' ),
226
  'default' => '',
@@ -229,7 +229,7 @@ class ES_Admin_Settings {
229
  'ig_es_optin_type' => array(
230
  'id' => 'ig_es_optin_type',
231
  'name' => __( 'Opt-in type', 'email-subscribers' ),
232
- 'info' => '',
233
  'desc' => __( 'Single = confirm subscribers as they subscribe.<br> Double = send a confirmation email and require clicking on a link to confirm subscription.', 'email-subscribers' ),
234
  'type' => 'select',
235
  'options' => ES_Common::get_optin_types(),
@@ -265,7 +265,7 @@ class ES_Admin_Settings {
265
  'default' => '',
266
  'id' => 'ig_es_form_submission_success_message',
267
  'name' => __( 'Subscription success message', 'email-subscribers' ),
268
- 'info' => __( 'This message will show when a visitor successfully subscribes using the form.', 'email-subscribers' ),
269
  'desc' => '',
270
  ),
271
 
@@ -277,7 +277,7 @@ class ES_Admin_Settings {
277
  'default' => '',
278
  'id' => 'ig_es_unsubscribe_link_content',
279
  'name' => __( 'Unsubscribe text in email footer:', 'email-subscribers' ),
280
- 'info' => __( 'All emails will include this text in the footer so people can unsubscribe if they want.', 'email-subscribers' ),
281
  /* translators: %s: List of Keywords */
282
  'desc' => sprintf( __( 'Use %s keyword to add unsubscribe link.', 'email-subscribers' ), '{{UNSUBSCRIBE-LINK}}' ),
283
  ),
@@ -343,16 +343,16 @@ class ES_Admin_Settings {
343
  ),
344
 
345
  // Start-IG-Code.
346
- 'ig_es_powered_by' => array(
347
  'id' => 'ig_es_powered_by',
348
  'name' => __( 'Share Icegram', 'email-subscribers' ),
349
- 'info' => __('Show "Powered By" link in the unsubscription form'),
350
  'type' => 'checkbox',
351
  'default' => 'yes',
352
  ),
353
  // End-IG-Code.
354
 
355
- 'ig_es_delete_plugin_data' => array(
356
  'id' => 'ig_es_delete_plugin_data',
357
  'name' => __( 'Delete plugin data on uninstall', 'email-subscribers' ),
358
  'info' => __( 'Be careful with this! When enabled, it will remove all lists, campaigns and other data if you uninstall the plugin.', 'email-subscribers' ),
@@ -511,7 +511,7 @@ class ES_Admin_Settings {
511
  $signup_confirmation_settings = apply_filters( 'ig_es_registered_signup_confirmation_settings', $signup_confirmation_settings );
512
 
513
  $cron_url_setting_desc = '';
514
-
515
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
516
  $cron_url_setting_desc = '<span class="es-send-success es-icon"></span>' . esc_html__( ' We will take care of it. You don\'t need to visit this URL manually.', 'email-subscribers' );
517
  } else {
@@ -519,7 +519,7 @@ class ES_Admin_Settings {
519
  $cron_url_setting_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' ), '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' );
520
  }
521
 
522
- $cron_url_setting_desc .= '<div class="mt-2.5 ml-1"><a class="hover:underline text-sm font-medium" href=" ' . esc_url( 'https://www.icegram.com/documentation/how-to-configure-email-sending-in-email-subscribers?utm_source=in_app&utm_medium=setup_email_sending&utm_campaign=es_doc') . '" target="_blank">' . esc_html__( 'How to configure Email Sending', 'email-subscribers' ) . '→</a></div>';
523
 
524
  $pepipost_api_key_defined = ES()->is_const_defined( 'pepipost', 'api_key' );
525
 
@@ -751,7 +751,6 @@ class ES_Admin_Settings {
751
  break;
752
  }
753
 
754
-
755
  // If there is help text
756
  if ( ! empty( $arguments['desc'] ) ) {
757
  $helper = $arguments['desc'];
@@ -813,7 +812,7 @@ class ES_Admin_Settings {
813
  $html .= '<div class="es_sub_headline ' . $class . ' pt-4" ><strong>' . $sub_field['name'] . '</strong>';
814
  if ( ! empty( $sub_field['tooltip_text'] ) ) {
815
  $tooltip_html = ES_Common::get_tooltip_html( $sub_field['tooltip_text'] );
816
- $html .= $tooltip_html;
817
  }
818
  $html .= '</div>';
819
  $html .= $this->field_callback( $sub_field, $field_key );
@@ -823,15 +822,15 @@ class ES_Admin_Settings {
823
  }
824
 
825
  if ( ! empty( $field['upgrade_desc'] ) ) {
826
- $upsell_info = array(
827
- 'upgrade_title' => $field[ 'upgrade_title' ],
828
- 'pricing_url' => $field[ 'link' ],
829
- 'upsell_message' => $field[ 'upgrade_desc' ],
830
- 'cta_html' => false,
831
  );
832
- $html .= '</div> <div class="w-3/5">';
833
- $html .= ES_Common::upsell_description_message_box( $upsell_info, false );
834
- $html .= '</div>';
835
  }
836
 
837
  $html .= '</td></tr>';
@@ -848,10 +847,10 @@ class ES_Admin_Settings {
848
  $html .= '</td></tr>';
849
  $html .= '</tbody>';
850
  $html .= '</table>';
851
-
852
- $allowedtags = ig_es_allowed_html_tags_in_esc();
853
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
854
- echo wp_kses( $html , $allowedtags );
855
  }
856
 
857
  /**
@@ -920,8 +919,8 @@ class ES_Admin_Settings {
920
  if ( ! empty( $mailer['is_premium'] ) ) {
921
  $html .= '<span class="premium-icon"></span>';
922
  }
923
-
924
- $html .= '</div>';
925
 
926
  if ( ! empty( $mailer['is_premium'] ) ) {
927
  $html .= '</a>';
@@ -936,9 +935,10 @@ class ES_Admin_Settings {
936
  public static function pepipost_doc_block() {
937
  $html = '';
938
 
939
- $url = ES_Common::get_utm_tracking_url( array(
940
- 'url' => 'https://www.icegram.com/email-subscribers-integrates-with-pepipost',
941
- 'utm_medium' => 'pepipost_doc'
 
942
  )
943
  );
944
 
@@ -948,7 +948,7 @@ class ES_Admin_Settings {
948
  <ul>
949
  <li><a class="" href="https://app.pepipost.com/index.php/signup/icegram?fpr=icegram" target="_blank"><?php esc_html_e( 'Signup for Pepipost', 'email-subscribers' ); ?></a></li>
950
  <li><?php esc_html_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 esc_html_e( 'Pepipost API key', 'email-subscribers' ); ?></a></li>
951
- <li><a href="<?php echo esc_url($url); ?>" target="_blank"><?php esc_html_e( 'Why to choose Pepipost', 'email-subscribers' ); ?></a></li>
952
  </ul>
953
  </div>
954
 
@@ -1004,7 +1004,7 @@ class ES_Admin_Settings {
1004
  'ig_es_cron',
1005
  'ig_es_cron_worker',
1006
  'ig_es_cron_auto_responder',
1007
- 'ig_es_summary_automation'
1008
  );
1009
 
1010
  $cron_schedules = wp_get_schedules();
@@ -1107,32 +1107,32 @@ class ES_Admin_Settings {
1107
 
1108
  /**
1109
  * Add setting for plugin usage tracking
1110
- *
1111
  * @param array $es_settings
1112
- *
1113
  * @return array $es_settings
1114
- *
1115
  * @since 4.7.7
1116
  */
1117
  public function show_usage_tracking_optin_setting( $es_settings ) {
1118
-
1119
  // Show option to enable/disable tracking if user isn't a premium user and trial is not valid i.e. has expired.
1120
  if ( ! ES()->is_premium() && ! ES()->is_trial_valid() ) {
1121
-
1122
- $allow_tracking = array(
1123
  'ig_es_allow_tracking' => array(
1124
  'id' => 'ig_es_allow_tracking',
1125
  'name' => __( 'Plugin usage tracking', 'email-subscribers' ),
1126
  'type' => 'checkbox',
1127
  'default' => 'no',
1128
- 'info' => __( 'Help us to improve Email Subscribers by opting in to share non-sensitive plugin usage data.', 'email-subscribers' ),
1129
- )
1130
  );
1131
-
1132
  $general_fields = $es_settings['general'];
1133
-
1134
  $general_fields = ig_es_array_insert_after( $general_fields, 'ig_es_intermediate_unsubscribe_page', $allow_tracking );
1135
-
1136
  $es_settings['general'] = $general_fields;
1137
  }
1138
 
21
 
22
  public function __construct() {
23
  add_filter( 'ig_es_registered_email_sending_settings', array( $this, 'show_cron_info' ) );
24
+
25
  // Start-IG-Code.
26
  // Add setting for plugin usage tracking
27
+ add_filter( 'ig_es_registered_settings', array( $this, 'show_usage_tracking_optin_setting' ), 30 );
28
  // End-IG-Code.
29
  }
30
 
45
 
46
  $options = apply_filters( 'ig_es_before_save_settings', $options );
47
 
48
+ $options['ig_es_disable_wp_cron'] = isset( $options['ig_es_disable_wp_cron'] ) ? $options['ig_es_disable_wp_cron'] : 'no';
49
+ $options['ig_es_track_email_opens'] = isset( $options['ig_es_track_email_opens'] ) ? $options['ig_es_track_email_opens'] : 'no';
50
+ $options['ig_es_enable_welcome_email'] = isset( $options['ig_es_enable_welcome_email'] ) ? $options['ig_es_enable_welcome_email'] : 'no';
51
+ $options['ig_es_notify_admin'] = isset( $options['ig_es_notify_admin'] ) ? $options['ig_es_notify_admin'] : 'no';
52
+ $options['ig_es_enable_cron_admin_email'] = isset( $options['ig_es_enable_cron_admin_email'] ) ? $options['ig_es_enable_cron_admin_email'] : 'no';
53
+ $options['ig_es_delete_plugin_data'] = isset( $options['ig_es_delete_plugin_data'] ) ? $options['ig_es_delete_plugin_data'] : 'no';
54
+ $options['ig_es_run_cron_on'] = isset( $options['ig_es_run_cron_on'] ) ? $options['ig_es_run_cron_on'] : 'monday';
55
+ $options['ig_es_run_cron_time'] = isset( $options['ig_es_run_cron_time'] ) ? $options['ig_es_run_cron_time'] : '4pm';
56
  // Start-IG-Code.
57
  // Show option to enable/disable tracking if user isn't a premium user and trial is not valid i.e. has expired.
58
  if ( ! ES()->is_premium() && ! ES()->is_trial_valid() ) {
59
  $options['ig_es_allow_tracking'] = isset( $options['ig_es_allow_tracking'] ) ? $options['ig_es_allow_tracking'] : 'no';
60
  }
61
+ $options['ig_es_powered_by'] = isset( $options['ig_es_powered_by'] ) ? $options['ig_es_powered_by'] : 'no';
62
  // End-IG-Code.
63
+
64
  $text_fields_to_sanitize = array(
65
  'ig_es_from_name',
66
  'ig_es_admin_emails',
122
  ES_Common::show_message( $message, $status );
123
  }
124
  }
125
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
126
 
127
  ?>
128
 
155
  'name' => __( 'Security', 'email-subscribers' ),
156
  ),
157
  );
158
+ $es_settings_tabs = apply_filters( 'ig_es_settings_tabs', $es_settings_tabs );
159
  ?>
160
  <div id="es-settings-menu" class="w-1/5 pt-4 leading-normal text-gray-800 border-r border-gray-100">
161
  <div class="z-20 my-2 mt-0 bg-white shadow es-menu-list lg:block lg:my-0 lg:border-transparent lg:shadow-none lg:bg-transparent" style="top:6em;" id="menu-content">
220
  'admin_email' => array(
221
  'id' => 'ig_es_admin_emails',
222
  'name' => __( 'Admin emails', 'email-subscribers' ),
223
+ 'info' => __( 'Who should be notified about system events like "someone subscribed", "campaign sent" etc?', 'email-subscribers' ),
224
  'type' => 'text',
225
  'desc' => __( 'You can enter multiple email addresses - separate them with comma', 'email-subscribers' ),
226
  'default' => '',
229
  'ig_es_optin_type' => array(
230
  'id' => 'ig_es_optin_type',
231
  'name' => __( 'Opt-in type', 'email-subscribers' ),
232
+ 'info' => '',
233
  'desc' => __( 'Single = confirm subscribers as they subscribe.<br> Double = send a confirmation email and require clicking on a link to confirm subscription.', 'email-subscribers' ),
234
  'type' => 'select',
235
  'options' => ES_Common::get_optin_types(),
265
  'default' => '',
266
  'id' => 'ig_es_form_submission_success_message',
267
  'name' => __( 'Subscription success message', 'email-subscribers' ),
268
+ 'info' => __( 'This message will show when a visitor successfully subscribes using the form.', 'email-subscribers' ),
269
  'desc' => '',
270
  ),
271
 
277
  'default' => '',
278
  'id' => 'ig_es_unsubscribe_link_content',
279
  'name' => __( 'Unsubscribe text in email footer:', 'email-subscribers' ),
280
+ 'info' => __( 'All emails will include this text in the footer so people can unsubscribe if they want.', 'email-subscribers' ),
281
  /* translators: %s: List of Keywords */
282
  'desc' => sprintf( __( 'Use %s keyword to add unsubscribe link.', 'email-subscribers' ), '{{UNSUBSCRIBE-LINK}}' ),
283
  ),
343
  ),
344
 
345
  // Start-IG-Code.
346
+ 'ig_es_powered_by' => array(
347
  'id' => 'ig_es_powered_by',
348
  'name' => __( 'Share Icegram', 'email-subscribers' ),
349
+ 'info' => __( 'Show "Powered By" link in the unsubscription form' ),
350
  'type' => 'checkbox',
351
  'default' => 'yes',
352
  ),
353
  // End-IG-Code.
354
 
355
+ 'ig_es_delete_plugin_data' => array(
356
  'id' => 'ig_es_delete_plugin_data',
357
  'name' => __( 'Delete plugin data on uninstall', 'email-subscribers' ),
358
  'info' => __( 'Be careful with this! When enabled, it will remove all lists, campaigns and other data if you uninstall the plugin.', 'email-subscribers' ),
511
  $signup_confirmation_settings = apply_filters( 'ig_es_registered_signup_confirmation_settings', $signup_confirmation_settings );
512
 
513
  $cron_url_setting_desc = '';
514
+
515
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
516
  $cron_url_setting_desc = '<span class="es-send-success es-icon"></span>' . esc_html__( ' We will take care of it. You don\'t need to visit this URL manually.', 'email-subscribers' );
517
  } else {
519
  $cron_url_setting_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' ), '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' );
520
  }
521
 
522
+ $cron_url_setting_desc .= '<div class="mt-2.5 ml-1"><a class="hover:underline text-sm font-medium" href=" ' . esc_url( 'https://www.icegram.com/documentation/how-to-configure-email-sending-in-email-subscribers?utm_source=in_app&utm_medium=setup_email_sending&utm_campaign=es_doc' ) . '" target="_blank">' . esc_html__( 'How to configure Email Sending', 'email-subscribers' ) . '→</a></div>';
523
 
524
  $pepipost_api_key_defined = ES()->is_const_defined( 'pepipost', 'api_key' );
525
 
751
  break;
752
  }
753
 
 
754
  // If there is help text
755
  if ( ! empty( $arguments['desc'] ) ) {
756
  $helper = $arguments['desc'];
812
  $html .= '<div class="es_sub_headline ' . $class . ' pt-4" ><strong>' . $sub_field['name'] . '</strong>';
813
  if ( ! empty( $sub_field['tooltip_text'] ) ) {
814
  $tooltip_html = ES_Common::get_tooltip_html( $sub_field['tooltip_text'] );
815
+ $html .= $tooltip_html;
816
  }
817
  $html .= '</div>';
818
  $html .= $this->field_callback( $sub_field, $field_key );
822
  }
823
 
824
  if ( ! empty( $field['upgrade_desc'] ) ) {
825
+ $upsell_info = array(
826
+ 'upgrade_title' => $field['upgrade_title'],
827
+ 'pricing_url' => $field['link'],
828
+ 'upsell_message' => $field['upgrade_desc'],
829
+ 'cta_html' => false,
830
  );
831
+ $html .= '</div> <div class="w-3/5">';
832
+ $html .= ES_Common::upsell_description_message_box( $upsell_info, false );
833
+ $html .= '</div>';
834
  }
835
 
836
  $html .= '</td></tr>';
847
  $html .= '</td></tr>';
848
  $html .= '</tbody>';
849
  $html .= '</table>';
850
+
851
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
852
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
853
+ echo wp_kses( $html, $allowedtags );
854
  }
855
 
856
  /**
919
  if ( ! empty( $mailer['is_premium'] ) ) {
920
  $html .= '<span class="premium-icon"></span>';
921
  }
922
+
923
+ $html .= '</div>';
924
 
925
  if ( ! empty( $mailer['is_premium'] ) ) {
926
  $html .= '</a>';
935
  public static function pepipost_doc_block() {
936
  $html = '';
937
 
938
+ $url = ES_Common::get_utm_tracking_url(
939
+ array(
940
+ 'url' => 'https://www.icegram.com/email-subscribers-integrates-with-pepipost',
941
+ 'utm_medium' => 'pepipost_doc',
942
  )
943
  );
944
 
948
  <ul>
949
  <li><a class="" href="https://app.pepipost.com/index.php/signup/icegram?fpr=icegram" target="_blank"><?php esc_html_e( 'Signup for Pepipost', 'email-subscribers' ); ?></a></li>
950
  <li><?php esc_html_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 esc_html_e( 'Pepipost API key', 'email-subscribers' ); ?></a></li>
951
+ <li><a href="<?php echo esc_url( $url ); ?>" target="_blank"><?php esc_html_e( 'Why to choose Pepipost', 'email-subscribers' ); ?></a></li>
952
  </ul>
953
  </div>
954
 
1004
  'ig_es_cron',
1005
  'ig_es_cron_worker',
1006
  'ig_es_cron_auto_responder',
1007
+ 'ig_es_summary_automation',
1008
  );
1009
 
1010
  $cron_schedules = wp_get_schedules();
1107
 
1108
  /**
1109
  * Add setting for plugin usage tracking
1110
+ *
1111
  * @param array $es_settings
1112
+ *
1113
  * @return array $es_settings
1114
+ *
1115
  * @since 4.7.7
1116
  */
1117
  public function show_usage_tracking_optin_setting( $es_settings ) {
1118
+
1119
  // Show option to enable/disable tracking if user isn't a premium user and trial is not valid i.e. has expired.
1120
  if ( ! ES()->is_premium() && ! ES()->is_trial_valid() ) {
1121
+
1122
+ $allow_tracking = array(
1123
  'ig_es_allow_tracking' => array(
1124
  'id' => 'ig_es_allow_tracking',
1125
  'name' => __( 'Plugin usage tracking', 'email-subscribers' ),
1126
  'type' => 'checkbox',
1127
  'default' => 'no',
1128
+ 'info' => __( 'Help us to improve Email Subscribers by opting in to share non-sensitive plugin usage data.', 'email-subscribers' ),
1129
+ ),
1130
  );
1131
+
1132
  $general_fields = $es_settings['general'];
1133
+
1134
  $general_fields = ig_es_array_insert_after( $general_fields, 'ig_es_intermediate_unsubscribe_page', $allow_tracking );
1135
+
1136
  $es_settings['general'] = $general_fields;
1137
  }
1138
 
lite/includes/classes/class-es-browser.php CHANGED
@@ -162,9 +162,9 @@ class ES_Browser {
162
  *
163
  * @param string $userAgent
164
  */
165
- public function __construct( $userAgent = '') {
166
  if ( '' != $userAgent ) {
167
- $this->setUserAgent($userAgent);
168
  } else {
169
  $this->reset();
170
  $this->determine();
@@ -175,7 +175,7 @@ class ES_Browser {
175
  * Reset all properties
176
  */
177
  public function reset() {
178
- $this->_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) : '';
179
  $this->_browser_name = self::BROWSER_UNKNOWN;
180
  $this->_version = self::VERSION_UNKNOWN;
181
  $this->_platform = self::PLATFORM_UNKNOWN;
@@ -194,8 +194,8 @@ class ES_Browser {
194
  * @param string $browserName
195
  * @return bool True if the browser is the specified browser
196
  */
197
- public function isBrowser( $browserName) {
198
- return ( 0 == strcasecmp($this->_browser_name, trim($browserName)) );
199
  }
200
 
201
  /**
@@ -212,7 +212,7 @@ class ES_Browser {
212
  *
213
  * @param $browser string The name of the Browser
214
  */
215
- public function setBrowser( $browser) {
216
  $this->_browser_name = $browser;
217
  }
218
 
@@ -230,7 +230,7 @@ class ES_Browser {
230
  *
231
  * @param string $platform The name of the Platform
232
  */
233
- public function setPlatform( $platform) {
234
  $this->_platform = $platform;
235
  }
236
 
@@ -248,8 +248,8 @@ class ES_Browser {
248
  *
249
  * @param string $version The version of the Browser
250
  */
251
- public function setVersion( $version) {
252
- $this->_version = preg_replace('/[^0-9,.,a-z,A-Z-]/', '', $version);
253
  }
254
 
255
  /**
@@ -266,8 +266,8 @@ class ES_Browser {
266
  *
267
  * @param string $version The version of AOL
268
  */
269
- public function setAolVersion( $version) {
270
- $this->_aol_version = preg_replace('/[^0-9,.,a-z,A-Z]/', '', $version);
271
  }
272
 
273
  /**
@@ -320,7 +320,7 @@ class ES_Browser {
320
  *
321
  * @param $isAol
322
  */
323
- public function setAol( $isAol) {
324
  $this->_is_aol = $isAol;
325
  }
326
 
@@ -329,7 +329,7 @@ class ES_Browser {
329
  *
330
  * @param boolean $value is the browser a mobile browser or not
331
  */
332
- protected function setMobile( $value = true) {
333
  $this->_is_mobile = $value;
334
  }
335
 
@@ -338,7 +338,7 @@ class ES_Browser {
338
  *
339
  * @param boolean $value is the browser a tablet browser or not
340
  */
341
- protected function setTablet( $value = true) {
342
  $this->_is_tablet = $value;
343
  }
344
 
@@ -347,7 +347,7 @@ class ES_Browser {
347
  *
348
  * @param boolean $value is the browser a robot or not
349
  */
350
- protected function setRobot( $value = true) {
351
  $this->_is_robot = $value;
352
  }
353
 
@@ -356,7 +356,7 @@ class ES_Browser {
356
  *
357
  * @param boolean $value is the browser a robot or not
358
  */
359
- protected function setFacebook( $value = true) {
360
  $this->_is_facebook = $value;
361
  }
362
 
@@ -374,7 +374,7 @@ class ES_Browser {
374
  *
375
  * @param string $agent_string The value for the User Agent
376
  */
377
- public function setUserAgent( $agent_string) {
378
  $this->reset();
379
  $this->_agent = $agent_string;
380
  $this->determine();
@@ -387,7 +387,7 @@ class ES_Browser {
387
  * @return boolean True if the browser is using chromeframe
388
  */
389
  public function isChromeFrame() {
390
- return ( strpos($this->_agent, 'chromeframe') !== false );
391
  }
392
 
393
  /**
@@ -421,17 +421,17 @@ class ES_Browser {
421
  // well-known, well-used
422
  // Special Notes:
423
  // (1) Opera must be checked before FireFox due to the odd
424
- // user agents used in some older versions of Opera
425
  // (2) WebTV is strapped onto Internet Explorer so we must
426
- // check for WebTV before IE
427
  // (3) (deprecated) Galeon is based on Firefox and needs to be
428
- // tested before Firefox is tested
429
  // (4) OmniWeb is based on Safari so OmniWeb check must occur
430
- // before Safari
431
  // (5) Netscape 9+ is based on Firefox so Netscape checks
432
- // before FireFox are necessary
433
  // (6) Vivaldi is UA contains both Firefox and Chrome so Vivaldi checks
434
- // before Firefox and Chrome
435
  $this->checkBrowserWebTv() ||
436
  $this->checkBrowserBrave() ||
437
  $this->checkBrowserUCBrowser() ||
@@ -509,13 +509,13 @@ class ES_Browser {
509
  * @return boolean True if the browser is the BlackBerry browser otherwise false
510
  */
511
  protected function checkBrowserBlackBerry() {
512
- if (stripos($this->_agent, 'blackberry') !== false) {
513
- $aresult = explode('/', stristr($this->_agent, 'BlackBerry'));
514
- if (isset($aresult[1])) {
515
- $aversion = explode(' ', $aresult[1]);
516
- $this->setVersion($aversion[0]);
517
  $this->_browser_name = self::BROWSER_BLACKBERRY;
518
- $this->setMobile(true);
519
  return true;
520
  }
521
  }
@@ -528,14 +528,14 @@ class ES_Browser {
528
  * @return boolean True if the browser is from AOL otherwise false
529
  */
530
  protected function checkForAol() {
531
- $this->setAol(false);
532
- $this->setAolVersion(self::VERSION_UNKNOWN);
533
-
534
- if (stripos($this->_agent, 'aol') !== false) {
535
- $aversion = explode(' ', stristr($this->_agent, 'AOL'));
536
- if (isset($aversion[1])) {
537
- $this->setAol(true);
538
- $this->setAolVersion(preg_replace('/[^0-9\.a-z]/i', '', $aversion[1]));
539
  return true;
540
  }
541
  }
@@ -548,13 +548,13 @@ class ES_Browser {
548
  * @return boolean True if the browser is the GoogletBot otherwise false
549
  */
550
  protected function checkBrowserGoogleBot() {
551
- if (stripos($this->_agent, 'googlebot') !== false) {
552
- $aresult = explode('/', stristr($this->_agent, 'googlebot'));
553
- if (isset($aresult[1])) {
554
- $aversion = explode(' ', $aresult[1]);
555
- $this->setVersion(str_replace(';', '', $aversion[0]));
556
  $this->_browser_name = self::BROWSER_GOOGLEBOT;
557
- $this->setRobot(true);
558
  return true;
559
  }
560
  }
@@ -567,13 +567,13 @@ class ES_Browser {
567
  * @return boolean True if the browser is the YandexBot otherwise false
568
  */
569
  protected function checkBrowserYandexBot() {
570
- if (stripos($this->_agent, 'YandexBot') !== false) {
571
- $aresult = explode('/', stristr($this->_agent, 'YandexBot'));
572
- if (isset($aresult[1])) {
573
- $aversion = explode(' ', $aresult[1]);
574
- $this->setVersion(str_replace(';', '', $aversion[0]));
575
  $this->_browser_name = self::BROWSER_YANDEXBOT;
576
- $this->setRobot(true);
577
  return true;
578
  }
579
  }
@@ -586,13 +586,13 @@ class ES_Browser {
586
  * @return boolean True if the browser is the YandexImageResizer otherwise false
587
  */
588
  protected function checkBrowserYandexImageResizerBot() {
589
- if (stripos($this->_agent, 'YandexImageResizer') !== false) {
590
- $aresult = explode('/', stristr($this->_agent, 'YandexImageResizer'));
591
- if (isset($aresult[1])) {
592
- $aversion = explode(' ', $aresult[1]);
593
- $this->setVersion(str_replace(';', '', $aversion[0]));
594
  $this->_browser_name = self::BROWSER_YANDEXIMAGERESIZER_BOT;
595
- $this->setRobot(true);
596
  return true;
597
  }
598
  }
@@ -605,13 +605,13 @@ class ES_Browser {
605
  * @return boolean True if the browser is the YandexCatalog otherwise false
606
  */
607
  protected function checkBrowserYandexCatalogBot() {
608
- if (stripos($this->_agent, 'YandexCatalog') !== false) {
609
- $aresult = explode('/', stristr($this->_agent, 'YandexCatalog'));
610
- if (isset($aresult[1])) {
611
- $aversion = explode(' ', $aresult[1]);
612
- $this->setVersion(str_replace(';', '', $aversion[0]));
613
  $this->_browser_name = self::BROWSER_YANDEXCATALOG_BOT;
614
- $this->setRobot(true);
615
  return true;
616
  }
617
  }
@@ -624,13 +624,13 @@ class ES_Browser {
624
  * @return boolean True if the browser is the YandexNews otherwise false
625
  */
626
  protected function checkBrowserYandexNewsBot() {
627
- if (stripos($this->_agent, 'YandexNews') !== false) {
628
- $aresult = explode('/', stristr($this->_agent, 'YandexNews'));
629
- if (isset($aresult[1])) {
630
- $aversion = explode(' ', $aresult[1]);
631
- $this->setVersion(str_replace(';', '', $aversion[0]));
632
  $this->_browser_name = self::BROWSER_YANDEXNEWS_BOT;
633
- $this->setRobot(true);
634
  return true;
635
  }
636
  }
@@ -643,13 +643,13 @@ class ES_Browser {
643
  * @return boolean True if the browser is the YandexMetrika otherwise false
644
  */
645
  protected function checkBrowserYandexMetrikaBot() {
646
- if (stripos($this->_agent, 'YandexMetrika') !== false) {
647
- $aresult = explode('/', stristr($this->_agent, 'YandexMetrika'));
648
- if (isset($aresult[1])) {
649
- $aversion = explode(' ', $aresult[1]);
650
- $this->setVersion(str_replace(';', '', $aversion[0]));
651
  $this->_browser_name = self::BROWSER_YANDEXMETRIKA_BOT;
652
- $this->setRobot(true);
653
  return true;
654
  }
655
  }
@@ -662,13 +662,13 @@ class ES_Browser {
662
  * @return boolean True if the browser is the YandexDirect otherwise false
663
  */
664
  protected function checkBrowserYandexDirectBot() {
665
- if (stripos($this->_agent, 'YandexDirect') !== false) {
666
- $aresult = explode('/', stristr($this->_agent, 'YandexDirect'));
667
- if (isset($aresult[1])) {
668
- $aversion = explode(' ', $aresult[1]);
669
- $this->setVersion(str_replace(';', '', $aversion[0]));
670
  $this->_browser_name = self::BROWSER_YANDEXDIRECT_BOT;
671
- $this->setRobot(true);
672
  return true;
673
  }
674
  }
@@ -681,13 +681,13 @@ class ES_Browser {
681
  * @return boolean True if the browser is the YandexWebmaster otherwise false
682
  */
683
  protected function checkBrowserYandexWebmasterBot() {
684
- if (stripos($this->_agent, 'YandexWebmaster') !== false) {
685
- $aresult = explode('/', stristr($this->_agent, 'YandexWebmaster'));
686
- if (isset($aresult[1])) {
687
- $aversion = explode(' ', $aresult[1]);
688
- $this->setVersion(str_replace(';', '', $aversion[0]));
689
  $this->_browser_name = self::BROWSER_YANDEXWEBMASTER_BOT;
690
- $this->setRobot(true);
691
  return true;
692
  }
693
  }
@@ -700,13 +700,13 @@ class ES_Browser {
700
  * @return boolean True if the browser is the YandexFavicons otherwise false
701
  */
702
  protected function checkBrowserYandexFaviconsBot() {
703
- if (stripos($this->_agent, 'YandexFavicons') !== false) {
704
- $aresult = explode('/', stristr($this->_agent, 'YandexFavicons'));
705
- if (isset($aresult[1])) {
706
- $aversion = explode(' ', $aresult[1]);
707
- $this->setVersion(str_replace(';', '', $aversion[0]));
708
  $this->_browser_name = self::BROWSER_YANDEXFAVICONS_BOT;
709
- $this->setRobot(true);
710
  return true;
711
  }
712
  }
@@ -719,13 +719,13 @@ class ES_Browser {
719
  * @return boolean True if the browser is the YandexBlogs otherwise false
720
  */
721
  protected function checkBrowserYandexBlogsBot() {
722
- if (stripos($this->_agent, 'YandexBlogs') !== false) {
723
- $aresult = explode('/', stristr($this->_agent, 'YandexBlogs'));
724
- if (isset($aresult[1])) {
725
- $aversion = explode(' ', $aresult[1]);
726
- $this->setVersion(str_replace(';', '', $aversion[0]));
727
  $this->_browser_name = self::BROWSER_YANDEXBLOGS_BOT;
728
- $this->setRobot(true);
729
  return true;
730
  }
731
  }
@@ -738,13 +738,13 @@ class ES_Browser {
738
  * @return boolean True if the browser is the YandexMedia otherwise false
739
  */
740
  protected function checkBrowserYandexMediaBot() {
741
- if (stripos($this->_agent, 'YandexMedia') !== false) {
742
- $aresult = explode('/', stristr($this->_agent, 'YandexMedia'));
743
- if (isset($aresult[1])) {
744
- $aversion = explode(' ', $aresult[1]);
745
- $this->setVersion(str_replace(';', '', $aversion[0]));
746
  $this->_browser_name = self::BROWSER_YANDEXMEDIA_BOT;
747
- $this->setRobot(true);
748
  return true;
749
  }
750
  }
@@ -757,13 +757,13 @@ class ES_Browser {
757
  * @return boolean True if the browser is the YandexVideo otherwise false
758
  */
759
  protected function checkBrowserYandexVideoBot() {
760
- if (stripos($this->_agent, 'YandexVideo') !== false) {
761
- $aresult = explode('/', stristr($this->_agent, 'YandexVideo'));
762
- if (isset($aresult[1])) {
763
- $aversion = explode(' ', $aresult[1]);
764
- $this->setVersion(str_replace(';', '', $aversion[0]));
765
  $this->_browser_name = self::BROWSER_YANDEXVIDEO_BOT;
766
- $this->setRobot(true);
767
  return true;
768
  }
769
  }
@@ -776,13 +776,13 @@ class ES_Browser {
776
  * @return boolean True if the browser is the YandexImages otherwise false
777
  */
778
  protected function checkBrowserYandexImagesBot() {
779
- if (stripos($this->_agent, 'YandexImages') !== false) {
780
- $aresult = explode('/', stristr($this->_agent, 'YandexImages'));
781
- if (isset($aresult[1])) {
782
- $aversion = explode(' ', $aresult[1]);
783
- $this->setVersion(str_replace(';', '', $aversion[0]));
784
  $this->_browser_name = self::BROWSER_YANDEXIMAGES_BOT;
785
- $this->setRobot(true);
786
  return true;
787
  }
788
  }
@@ -795,13 +795,13 @@ class ES_Browser {
795
  * @return boolean True if the browser is the MSNBot otherwise false
796
  */
797
  protected function checkBrowserMSNBot() {
798
- if (stripos($this->_agent, 'msnbot') !== false) {
799
- $aresult = explode('/', stristr($this->_agent, 'msnbot'));
800
- if (isset($aresult[1])) {
801
- $aversion = explode(' ', $aresult[1]);
802
- $this->setVersion(str_replace(';', '', $aversion[0]));
803
  $this->_browser_name = self::BROWSER_MSNBOT;
804
- $this->setRobot(true);
805
  return true;
806
  }
807
  }
@@ -814,13 +814,13 @@ class ES_Browser {
814
  * @return boolean True if the browser is the BingBot otherwise false
815
  */
816
  protected function checkBrowserBingBot() {
817
- if (stripos($this->_agent, 'bingbot') !== false) {
818
- $aresult = explode('/', stristr($this->_agent, 'bingbot'));
819
- if (isset($aresult[1])) {
820
- $aversion = explode(' ', $aresult[1]);
821
- $this->setVersion(str_replace(';', '', $aversion[0]));
822
  $this->_browser_name = self::BROWSER_BINGBOT;
823
- $this->setRobot(true);
824
  return true;
825
  }
826
  }
@@ -833,27 +833,27 @@ class ES_Browser {
833
  * @return boolean True if the browser is the W3C Validator otherwise false
834
  */
835
  protected function checkBrowserW3CValidator() {
836
- if (stripos($this->_agent, 'W3C-checklink') !== false) {
837
- $aresult = explode('/', stristr($this->_agent, 'W3C-checklink'));
838
- if (isset($aresult[1])) {
839
- $aversion = explode(' ', $aresult[1]);
840
- $this->setVersion($aversion[0]);
841
  $this->_browser_name = self::BROWSER_W3CVALIDATOR;
842
  return true;
843
  }
844
- } elseif (stripos($this->_agent, 'W3C_Validator') !== false) {
845
  // Some of the Validator versions do not delineate w/ a slash - add it back in
846
- $ua = str_replace('W3C_Validator ', 'W3C_Validator/', $this->_agent);
847
- $aresult = explode('/', stristr($ua, 'W3C_Validator'));
848
- if (isset($aresult[1])) {
849
- $aversion = explode(' ', $aresult[1]);
850
- $this->setVersion($aversion[0]);
851
  $this->_browser_name = self::BROWSER_W3CVALIDATOR;
852
  return true;
853
  }
854
- } elseif (stripos($this->_agent, 'W3C-mobileOK') !== false) {
855
  $this->_browser_name = self::BROWSER_W3CVALIDATOR;
856
- $this->setMobile(true);
857
  return true;
858
  }
859
  return false;
@@ -865,14 +865,14 @@ class ES_Browser {
865
  * @return boolean True if the browser is the Yahoo! Slurp Robot otherwise false
866
  */
867
  protected function checkBrowserSlurp() {
868
- if (stripos($this->_agent, 'slurp') !== false) {
869
- $aresult = explode('/', stristr($this->_agent, 'Slurp'));
870
- if (isset($aresult[1])) {
871
- $aversion = explode(' ', $aresult[1]);
872
- $this->setVersion($aversion[0]);
873
  $this->_browser_name = self::BROWSER_SLURP;
874
- $this->setRobot(true);
875
- $this->setMobile(false);
876
  return true;
877
  }
878
  }
@@ -885,19 +885,19 @@ class ES_Browser {
885
  * @return boolean True if the browser is Brave otherwise false
886
  */
887
  protected function checkBrowserBrave() {
888
- if (stripos($this->_agent, 'Brave/') !== false) {
889
- $aResult = explode('/', stristr($this->_agent, 'Brave'));
890
- if (isset($aResult[1])) {
891
- $aversion = explode(' ', $aResult[1]);
892
- $this->setVersion($aversion[0]);
893
- $this->setBrowser(self::BROWSER_BRAVE);
894
  return true;
895
  }
896
- } elseif (stripos($this->_agent, ' Brave ') !== false) {
897
- $this->setBrowser(self::BROWSER_BRAVE);
898
  // this version of the UA did not ship with a version marker
899
  // e.g. Mozilla/5.0 (Linux; Android 7.0; SM-G955F Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/68.0.3440.91 Mobile Safari/537.36
900
- $this->setVersion('');
901
  return true;
902
  }
903
  return false;
@@ -909,16 +909,16 @@ class ES_Browser {
909
  * @return boolean True if the browser is Edge otherwise false
910
  */
911
  protected function checkBrowserEdge() {
912
- $short_edg = stripos($this->_agent, 'Edg/') !== false || stripos($this->_agent, 'EdgA/') !== false ? 'Edg' : false;
913
- $name = stripos($this->_agent, 'Edge/') !== false ? 'Edge' : $short_edg;
914
  if ( $name ) {
915
- $aresult = explode('/', stristr($this->_agent, $name));
916
- if (isset($aresult[1])) {
917
- $aversion = explode(' ', $aresult[1]);
918
- $this->setVersion($aversion[0]);
919
- $this->setBrowser(self::BROWSER_EDGE);
920
- if (stripos($this->_agent, 'Windows Phone') !== false || stripos($this->_agent, 'Android') !== false) {
921
- $this->setMobile(true);
922
  }
923
  return true;
924
  }
@@ -932,63 +932,63 @@ class ES_Browser {
932
  * @return boolean True if the browser is Internet Explorer otherwise false
933
  */
934
  protected function checkBrowserInternetExplorer() {
935
- // Test for IE11
936
- if (stripos($this->_agent, 'Trident/7.0; rv:11.0') !== false) {
937
- $this->setBrowser(self::BROWSER_IE);
938
- $this->setVersion('11.0');
939
  return true;
940
- } elseif (stripos($this->_agent, 'microsoft internet explorer') !== false) {
941
  // Test for v1 - v1.5 IE
942
- $this->setBrowser(self::BROWSER_IE);
943
- $this->setVersion('1.0');
944
- $aresult = stristr($this->_agent, '/');
945
- if (preg_match('/308|425|426|474|0b1/i', $aresult)) {
946
- $this->setVersion('1.5');
947
  }
948
  return true;
949
- } elseif (stripos($this->_agent, 'msie') !== false && stripos($this->_agent, 'opera') === false) {
950
  // Test for versions > 1.5
951
  // See if the browser is the odd MSN Explorer
952
- if (stripos($this->_agent, 'msnb') !== false) {
953
- $aresult = explode(' ', stristr(str_replace(';', '; ', $this->_agent), 'MSN'));
954
- if (isset($aresult[1])) {
955
- $this->setBrowser(self::BROWSER_MSN);
956
- $this->setVersion(str_replace(array('(', ')', ';'), '', $aresult[1]));
957
  return true;
958
  }
959
  }
960
- $aresult = explode(' ', stristr(str_replace(';', '; ', $this->_agent), 'msie'));
961
- if (isset($aresult[1])) {
962
- $this->setBrowser(self::BROWSER_IE);
963
- $this->setVersion(str_replace(array('(', ')', ';'), '', $aresult[1]));
964
- if (stripos($this->_agent, 'IEMobile') !== false) {
965
- $this->setBrowser(self::BROWSER_POCKET_IE);
966
- $this->setMobile(true);
967
  }
968
  return true;
969
  }
970
- } elseif (stripos($this->_agent, 'trident') !== false) {
971
  // Test for versions > IE 10
972
- $this->setBrowser(self::BROWSER_IE);
973
- $result = explode('rv:', $this->_agent);
974
- if (isset($result[1])) {
975
- $this->setVersion(preg_replace('/[^0-9.]+/', '', $result[1]));
976
- $this->_agent = str_replace(array('Mozilla', 'Gecko'), 'MSIE', $this->_agent);
977
  }
978
- } elseif (stripos($this->_agent, 'mspie') !== false || stripos($this->_agent, 'pocket') !== false) {
979
  // Test for Pocket IE
980
- $aresult = explode(' ', stristr($this->_agent, 'mspie'));
981
- if (isset($aresult[1])) {
982
- $this->setPlatform(self::PLATFORM_WINDOWS_CE);
983
- $this->setBrowser(self::BROWSER_POCKET_IE);
984
- $this->setMobile(true);
985
-
986
- if (stripos($this->_agent, 'mspie') !== false) {
987
- $this->setVersion($aresult[1]);
988
  } else {
989
- $aversion = explode('/', $this->_agent);
990
- if (isset($aversion[1])) {
991
- $this->setVersion($aversion[1]);
992
  }
993
  }
994
  return true;
@@ -1003,53 +1003,53 @@ class ES_Browser {
1003
  * @return boolean True if the browser is Opera otherwise false
1004
  */
1005
  protected function checkBrowserOpera() {
1006
- if (stripos($this->_agent, 'opera mini') !== false) {
1007
- $resultant = stristr($this->_agent, 'opera mini');
1008
- if (preg_match('/\//', $resultant)) {
1009
- $aresult = explode('/', $resultant);
1010
- if (isset($aresult[1])) {
1011
- $aversion = explode(' ', $aresult[1]);
1012
- $this->setVersion($aversion[0]);
1013
  }
1014
  } else {
1015
- $aversion = explode(' ', stristr($resultant, 'opera mini'));
1016
- if (isset($aversion[1])) {
1017
- $this->setVersion($aversion[1]);
1018
  }
1019
  }
1020
  $this->_browser_name = self::BROWSER_OPERA_MINI;
1021
- $this->setMobile(true);
1022
  return true;
1023
- } elseif (stripos($this->_agent, 'opera') !== false) {
1024
- $resultant = stristr($this->_agent, 'opera');
1025
- if (preg_match('/Version\/(1*.*)$/', $resultant, $matches)) {
1026
- $this->setVersion($matches[1]);
1027
- } elseif (preg_match('/\//', $resultant)) {
1028
- $aresult = explode('/', str_replace('(', ' ', $resultant));
1029
- if (isset($aresult[1])) {
1030
- $aversion = explode(' ', $aresult[1]);
1031
- $this->setVersion($aversion[0]);
1032
  }
1033
  } else {
1034
- $aversion = explode(' ', stristr($resultant, 'opera'));
1035
- $this->setVersion(isset($aversion[1]) ? $aversion[1] : '');
1036
  }
1037
- if (stripos($this->_agent, 'Opera Mobi') !== false) {
1038
- $this->setMobile(true);
1039
  }
1040
  $this->_browser_name = self::BROWSER_OPERA;
1041
  return true;
1042
- } elseif (stripos($this->_agent, 'OPR') !== false) {
1043
- $resultant = stristr($this->_agent, 'OPR');
1044
- if (preg_match('/\//', $resultant)) {
1045
- $aresult = explode('/', str_replace('(', ' ', $resultant));
1046
- if (isset($aresult[1])) {
1047
- $aversion = explode(' ', $aresult[1]);
1048
- $this->setVersion($aversion[0]);
1049
  }
1050
  }
1051
- if (stripos($this->_agent, 'Mobile') !== false) {
1052
- $this->setMobile(true);
1053
  }
1054
  $this->_browser_name = self::BROWSER_OPERA;
1055
  return true;
@@ -1063,18 +1063,18 @@ class ES_Browser {
1063
  * @return boolean True if the browser is Chrome otherwise false
1064
  */
1065
  protected function checkBrowserChrome() {
1066
- if (stripos($this->_agent, 'Chrome') !== false) {
1067
- $aresult = preg_split('/[\/;]+/', stristr($this->_agent, 'Chrome'));
1068
- if (isset($aresult[1])) {
1069
- $aversion = explode(' ', $aresult[1]);
1070
- $this->setVersion($aversion[0]);
1071
- $this->setBrowser(self::BROWSER_CHROME);
1072
- //Chrome on Android
1073
- if (stripos($this->_agent, 'Android') !== false) {
1074
- if (stripos($this->_agent, 'Mobile') !== false) {
1075
- $this->setMobile(true);
1076
  } else {
1077
- $this->setTablet(true);
1078
  }
1079
  }
1080
  return true;
@@ -1090,12 +1090,12 @@ class ES_Browser {
1090
  * @return boolean True if the browser is WebTv otherwise false
1091
  */
1092
  protected function checkBrowserWebTv() {
1093
- if (stripos($this->_agent, 'webtv') !== false) {
1094
- $aresult = explode('/', stristr($this->_agent, 'webtv'));
1095
- if (isset($aresult[1])) {
1096
- $aversion = explode(' ', $aresult[1]);
1097
- $this->setVersion($aversion[0]);
1098
- $this->setBrowser(self::BROWSER_WEBTV);
1099
  return true;
1100
  }
1101
  }
@@ -1108,12 +1108,12 @@ class ES_Browser {
1108
  * @return boolean True if the browser is NetPositive otherwise false
1109
  */
1110
  protected function checkBrowserNetPositive() {
1111
- if (stripos($this->_agent, 'NetPositive') !== false) {
1112
- $aresult = explode('/', stristr($this->_agent, 'NetPositive'));
1113
- if (isset($aresult[1])) {
1114
- $aversion = explode(' ', $aresult[1]);
1115
- $this->setVersion(str_replace(array('(', ')', ';'), '', $aversion[0]));
1116
- $this->setBrowser(self::BROWSER_NETPOSITIVE);
1117
  return true;
1118
  }
1119
  }
@@ -1126,12 +1126,12 @@ class ES_Browser {
1126
  * @return boolean True if the browser is Galeon otherwise false
1127
  */
1128
  protected function checkBrowserGaleon() {
1129
- if (stripos($this->_agent, 'galeon') !== false) {
1130
- $aresult = explode(' ', stristr($this->_agent, 'galeon'));
1131
- $aversion = explode('/', $aresult[0]);
1132
- if (isset($aversion[1])) {
1133
- $this->setVersion($aversion[1]);
1134
- $this->setBrowser(self::BROWSER_GALEON);
1135
  return true;
1136
  }
1137
  }
@@ -1144,12 +1144,12 @@ class ES_Browser {
1144
  * @return boolean True if the browser is Konqueror otherwise false
1145
  */
1146
  protected function checkBrowserKonqueror() {
1147
- if (stripos($this->_agent, 'Konqueror') !== false) {
1148
- $aresult = explode(' ', stristr($this->_agent, 'Konqueror'));
1149
- $aversion = explode('/', $aresult[0]);
1150
- if (isset($aversion[1])) {
1151
- $this->setVersion($aversion[1]);
1152
- $this->setBrowser(self::BROWSER_KONQUEROR);
1153
  return true;
1154
  }
1155
  }
@@ -1162,11 +1162,11 @@ class ES_Browser {
1162
  * @return boolean True if the browser is iCab otherwise false
1163
  */
1164
  protected function checkBrowserIcab() {
1165
- if (stripos($this->_agent, 'icab') !== false) {
1166
- $aversion = explode(' ', stristr(str_replace('/', ' ', $this->_agent), 'icab'));
1167
- if (isset($aversion[1])) {
1168
- $this->setVersion($aversion[1]);
1169
- $this->setBrowser(self::BROWSER_ICAB);
1170
  return true;
1171
  }
1172
  }
@@ -1179,11 +1179,11 @@ class ES_Browser {
1179
  * @return boolean True if the browser is OmniWeb otherwise false
1180
  */
1181
  protected function checkBrowserOmniWeb() {
1182
- if (stripos($this->_agent, 'omniweb') !== false) {
1183
- $aresult = explode('/', stristr($this->_agent, 'omniweb'));
1184
- $aversion = explode(' ', isset($aresult[1]) ? $aresult[1] : '');
1185
- $this->setVersion($aversion[0]);
1186
- $this->setBrowser(self::BROWSER_OMNIWEB);
1187
  return true;
1188
  }
1189
  return false;
@@ -1195,11 +1195,11 @@ class ES_Browser {
1195
  * @return boolean True if the browser is Phoenix otherwise false
1196
  */
1197
  protected function checkBrowserPhoenix() {
1198
- if (stripos($this->_agent, 'Phoenix') !== false) {
1199
- $aversion = explode('/', stristr($this->_agent, 'Phoenix'));
1200
- if (isset($aversion[1])) {
1201
- $this->setVersion($aversion[1]);
1202
- $this->setBrowser(self::BROWSER_PHOENIX);
1203
  return true;
1204
  }
1205
  }
@@ -1212,11 +1212,11 @@ class ES_Browser {
1212
  * @return boolean True if the browser is Firebird otherwise false
1213
  */
1214
  protected function checkBrowserFirebird() {
1215
- if (stripos($this->_agent, 'Firebird') !== false) {
1216
- $aversion = explode('/', stristr($this->_agent, 'Firebird'));
1217
- if (isset($aversion[1])) {
1218
- $this->setVersion($aversion[1]);
1219
- $this->setBrowser(self::BROWSER_FIREBIRD);
1220
  return true;
1221
  }
1222
  }
@@ -1230,13 +1230,13 @@ class ES_Browser {
1230
  * @return boolean True if the browser is Netscape Navigator 9+ otherwise false
1231
  */
1232
  protected function checkBrowserNetscapeNavigator9Plus() {
1233
- if (stripos($this->_agent, 'Firefox') !== false && preg_match('/Navigator\/([^ ]*)/i', $this->_agent, $matches)) {
1234
- $this->setVersion($matches[1]);
1235
- $this->setBrowser(self::BROWSER_NETSCAPE_NAVIGATOR);
1236
  return true;
1237
- } elseif (stripos($this->_agent, 'Firefox') === false && preg_match('/Netscape6?\/([^ ]*)/i', $this->_agent, $matches)) {
1238
- $this->setVersion($matches[1]);
1239
- $this->setBrowser(self::BROWSER_NETSCAPE_NAVIGATOR);
1240
  return true;
1241
  }
1242
  return false;
@@ -1248,9 +1248,9 @@ class ES_Browser {
1248
  * @return boolean True if the browser is Shiretoko otherwise false
1249
  */
1250
  protected function checkBrowserShiretoko() {
1251
- if (stripos($this->_agent, 'Mozilla') !== false && preg_match('/Shiretoko\/([^ ]*)/i', $this->_agent, $matches)) {
1252
- $this->setVersion($matches[1]);
1253
- $this->setBrowser(self::BROWSER_SHIRETOKO);
1254
  return true;
1255
  }
1256
  return false;
@@ -1262,9 +1262,9 @@ class ES_Browser {
1262
  * @return boolean True if the browser is Ice Cat otherwise false
1263
  */
1264
  protected function checkBrowserIceCat() {
1265
- if (stripos($this->_agent, 'Mozilla') !== false && preg_match('/IceCat\/([^ ]*)/i', $this->_agent, $matches)) {
1266
- $this->setVersion($matches[1]);
1267
- $this->setBrowser(self::BROWSER_ICECAT);
1268
  return true;
1269
  }
1270
  return false;
@@ -1276,14 +1276,14 @@ class ES_Browser {
1276
  * @return boolean True if the browser is Nokia otherwise false
1277
  */
1278
  protected function checkBrowserNokia() {
1279
- if (preg_match('/Nokia([^\/]+)\/([^ SP]+)/i', $this->_agent, $matches)) {
1280
- $this->setVersion($matches[2]);
1281
- if (stripos($this->_agent, 'Series60') !== false || strpos($this->_agent, 'S60') !== false) {
1282
- $this->setBrowser(self::BROWSER_NOKIA_S60);
1283
  } else {
1284
- $this->setBrowser(self::BROWSER_NOKIA);
1285
  }
1286
- $this->setMobile(true);
1287
  return true;
1288
  }
1289
  return false;
@@ -1295,18 +1295,18 @@ class ES_Browser {
1295
  * @return boolean True if the browser is Palemoon otherwise false
1296
  */
1297
  protected function checkBrowserPalemoon() {
1298
- if (stripos($this->_agent, 'safari') === false) {
1299
- if (preg_match('/Palemoon[\/ \(]([^ ;\)]+)/i', $this->_agent, $matches)) {
1300
- $this->setVersion($matches[1]);
1301
- $this->setBrowser(self::BROWSER_PALEMOON);
1302
  return true;
1303
- } elseif (preg_match('/Palemoon([0-9a-zA-Z\.]+)/i', $this->_agent, $matches)) {
1304
- $this->setVersion($matches[1]);
1305
- $this->setBrowser(self::BROWSER_PALEMOON);
1306
  return true;
1307
- } elseif (preg_match('/Palemoon/i', $this->_agent, $matches)) {
1308
- $this->setVersion('');
1309
- $this->setBrowser(self::BROWSER_PALEMOON);
1310
  return true;
1311
  }
1312
  }
@@ -1319,16 +1319,16 @@ class ES_Browser {
1319
  * @return boolean True if the browser is UCBrowser otherwise false
1320
  */
1321
  protected function checkBrowserUCBrowser() {
1322
- if (preg_match('/UC ?Browser\/?([\d\.]+)/', $this->_agent, $matches)) {
1323
- if (isset($matches[1])) {
1324
- $this->setVersion($matches[1]);
1325
  }
1326
- if (stripos($this->_agent, 'Mobile') !== false) {
1327
- $this->setMobile(true);
1328
  } else {
1329
- $this->setTablet(true);
1330
  }
1331
- $this->setBrowser(self::BROWSER_UCBROWSER);
1332
  return true;
1333
  }
1334
  return false;
@@ -1340,37 +1340,37 @@ class ES_Browser {
1340
  * @return boolean True if the browser is Firefox otherwise false
1341
  */
1342
  protected function checkBrowserFirefox() {
1343
- if (stripos($this->_agent, 'safari') === false) {
1344
- if (preg_match('/Firefox[\/ \(]([^ ;\)]+)/i', $this->_agent, $matches)) {
1345
- $this->setVersion($matches[1]);
1346
- $this->setBrowser(self::BROWSER_FIREFOX);
1347
- //Firefox on Android
1348
- if (stripos($this->_agent, 'Android') !== false || stripos($this->_agent, 'iPhone') !== false) {
1349
- if (stripos($this->_agent, 'Mobile') !== false || stripos($this->_agent, 'Tablet') !== false) {
1350
- $this->setMobile(true);
1351
  } else {
1352
- $this->setTablet(true);
1353
  }
1354
  }
1355
  return true;
1356
- } elseif (preg_match('/Firefox([0-9a-zA-Z\.]+)/i', $this->_agent, $matches)) {
1357
- $this->setVersion($matches[1]);
1358
- $this->setBrowser(self::BROWSER_FIREFOX);
1359
  return true;
1360
- } elseif (preg_match('/Firefox$/i', $this->_agent, $matches)) {
1361
- $this->setVersion('');
1362
- $this->setBrowser(self::BROWSER_FIREFOX);
1363
  return true;
1364
  }
1365
- } elseif (preg_match('/FxiOS[\/ \(]([^ ;\)]+)/i', $this->_agent, $matches)) {
1366
- $this->setVersion($matches[1]);
1367
- $this->setBrowser(self::BROWSER_FIREFOX);
1368
- //Firefox on Android
1369
- if (stripos($this->_agent, 'Android') !== false || stripos($this->_agent, 'iPhone') !== false) {
1370
- if (stripos($this->_agent, 'Mobile') !== false || stripos($this->_agent, 'Tablet') !== false) {
1371
- $this->setMobile(true);
1372
  } else {
1373
- $this->setTablet(true);
1374
  }
1375
  }
1376
  return true;
@@ -1384,12 +1384,12 @@ class ES_Browser {
1384
  * @return boolean True if the browser is Firefox otherwise false
1385
  */
1386
  protected function checkBrowserIceweasel() {
1387
- if (stripos($this->_agent, 'Iceweasel') !== false) {
1388
- $aresult = explode('/', stristr($this->_agent, 'Iceweasel'));
1389
- if (isset($aresult[1])) {
1390
- $aversion = explode(' ', $aresult[1]);
1391
- $this->setVersion($aversion[0]);
1392
- $this->setBrowser(self::BROWSER_ICEWEASEL);
1393
  return true;
1394
  }
1395
  }
@@ -1402,20 +1402,20 @@ class ES_Browser {
1402
  * @return boolean True if the browser is Mozilla otherwise false
1403
  */
1404
  protected function checkBrowserMozilla() {
1405
- if (stripos($this->_agent, 'mozilla') !== false && preg_match('/rv:[0-9].[0-9][a-b]?/i', $this->_agent) && stripos($this->_agent, 'netscape') === false) {
1406
- $aversion = explode(' ', stristr($this->_agent, 'rv:'));
1407
- preg_match('/rv:[0-9].[0-9][a-b]?/i', $this->_agent, $aversion);
1408
- $this->setVersion(str_replace('rv:', '', $aversion[0]));
1409
- $this->setBrowser(self::BROWSER_MOZILLA);
1410
  return true;
1411
- } elseif (stripos($this->_agent, 'mozilla') !== false && preg_match('/rv:[0-9]\.[0-9]/i', $this->_agent) && stripos($this->_agent, 'netscape') === false) {
1412
- $aversion = explode('', stristr($this->_agent, 'rv:'));
1413
- $this->setVersion(str_replace('rv:', '', $aversion[0]));
1414
- $this->setBrowser(self::BROWSER_MOZILLA);
1415
  return true;
1416
- } elseif (stripos($this->_agent, 'mozilla') !== false && preg_match('/mozilla\/([^ ]*)/i', $this->_agent, $matches) && stripos($this->_agent, 'netscape') === false) {
1417
- $this->setVersion($matches[1]);
1418
- $this->setBrowser(self::BROWSER_MOZILLA);
1419
  return true;
1420
  }
1421
  return false;
@@ -1427,11 +1427,11 @@ class ES_Browser {
1427
  * @return boolean True if the browser is Lynx otherwise false
1428
  */
1429
  protected function checkBrowserLynx() {
1430
- if (stripos($this->_agent, 'lynx') !== false) {
1431
- $aresult = explode('/', stristr($this->_agent, 'Lynx'));
1432
- $aversion = explode(' ', ( isset($aresult[1]) ? $aresult[1] : '' ));
1433
- $this->setVersion($aversion[0]);
1434
- $this->setBrowser(self::BROWSER_LYNX);
1435
  return true;
1436
  }
1437
  return false;
@@ -1443,12 +1443,12 @@ class ES_Browser {
1443
  * @return boolean True if the browser is Amaya otherwise false
1444
  */
1445
  protected function checkBrowserAmaya() {
1446
- if (stripos($this->_agent, 'amaya') !== false) {
1447
- $aresult = explode('/', stristr($this->_agent, 'Amaya'));
1448
- if (isset($aresult[1])) {
1449
- $aversion = explode(' ', $aresult[1]);
1450
- $this->setVersion($aversion[0]);
1451
- $this->setBrowser(self::BROWSER_AMAYA);
1452
  return true;
1453
  }
1454
  }
@@ -1462,80 +1462,80 @@ class ES_Browser {
1462
  */
1463
  protected function checkBrowserSafari() {
1464
  if (
1465
- stripos($this->_agent, 'Safari') !== false
1466
- && stripos($this->_agent, 'iPhone') === false
1467
- && stripos($this->_agent, 'iPod') === false
1468
  ) {
1469
 
1470
- $aresult = explode('/', stristr($this->_agent, 'Version'));
1471
- if (isset($aresult[1])) {
1472
- $aversion = explode(' ', $aresult[1]);
1473
- $this->setVersion($aversion[0]);
1474
  } else {
1475
- $this->setVersion(self::VERSION_UNKNOWN);
1476
  }
1477
- $this->setBrowser(self::BROWSER_SAFARI);
1478
  return true;
1479
  }
1480
  return false;
1481
  }
1482
 
1483
  protected function checkBrowserSamsung() {
1484
- if (stripos($this->_agent, 'SamsungBrowser') !== false) {
1485
 
1486
- $aresult = explode('/', stristr($this->_agent, 'SamsungBrowser'));
1487
- if (isset($aresult[1])) {
1488
- $aversion = explode(' ', $aresult[1]);
1489
- $this->setVersion($aversion[0]);
1490
  } else {
1491
- $this->setVersion(self::VERSION_UNKNOWN);
1492
  }
1493
- $this->setBrowser(self::BROWSER_SAMSUNG);
1494
  return true;
1495
  }
1496
  return false;
1497
  }
1498
 
1499
  protected function checkBrowserSilk() {
1500
- if (stripos($this->_agent, 'Silk') !== false) {
1501
- $aresult = explode('/', stristr($this->_agent, 'Silk'));
1502
- if (isset($aresult[1])) {
1503
- $aversion = explode(' ', $aresult[1]);
1504
- $this->setVersion($aversion[0]);
1505
  } else {
1506
- $this->setVersion(self::VERSION_UNKNOWN);
1507
  }
1508
- $this->setBrowser(self::BROWSER_SILK);
1509
  return true;
1510
  }
1511
  return false;
1512
  }
1513
 
1514
  protected function checkBrowserIframely() {
1515
- if (stripos($this->_agent, 'Iframely') !== false) {
1516
- $aresult = explode('/', stristr($this->_agent, 'Iframely'));
1517
- if (isset($aresult[1])) {
1518
- $aversion = explode(' ', $aresult[1]);
1519
- $this->setVersion($aversion[0]);
1520
  } else {
1521
- $this->setVersion(self::VERSION_UNKNOWN);
1522
  }
1523
- $this->setBrowser(self::BROWSER_I_FRAME);
1524
  return true;
1525
  }
1526
  return false;
1527
  }
1528
 
1529
  protected function checkBrowserCocoa() {
1530
- if (stripos($this->_agent, 'CocoaRestClient') !== false) {
1531
- $aresult = explode('/', stristr($this->_agent, 'CocoaRestClient'));
1532
- if (isset($aresult[1])) {
1533
- $aversion = explode(' ', $aresult[1]);
1534
- $this->setVersion($aversion[0]);
1535
  } else {
1536
- $this->setVersion(self::VERSION_UNKNOWN);
1537
  }
1538
- $this->setBrowser(self::BROWSER_COCOA);
1539
  return true;
1540
  }
1541
  return false;
@@ -1547,9 +1547,9 @@ class ES_Browser {
1547
  * @return boolean True if it detects FacebookExternalHit otherwise false
1548
  */
1549
  protected function checkFacebookExternalHit() {
1550
- if (stristr($this->_agent, 'FacebookExternalHit')) {
1551
- $this->setRobot(true);
1552
- $this->setFacebook(true);
1553
  return true;
1554
  }
1555
  return false;
@@ -1561,8 +1561,8 @@ class ES_Browser {
1561
  * @return boolean True if it detects internal Facebook browser otherwise false
1562
  */
1563
  protected function checkForFacebookIos() {
1564
- if (stristr($this->_agent, 'FBIOS')) {
1565
- $this->setFacebook(true);
1566
  return true;
1567
  }
1568
  return false;
@@ -1574,10 +1574,10 @@ class ES_Browser {
1574
  * @return boolean True if it detects the version correctly otherwise false
1575
  */
1576
  protected function getSafariVersionOnIos() {
1577
- $aresult = explode('/', stristr($this->_agent, 'Version'));
1578
- if (isset($aresult[1])) {
1579
- $aversion = explode(' ', $aresult[1]);
1580
- $this->setVersion($aversion[0]);
1581
  return true;
1582
  }
1583
  return false;
@@ -1589,11 +1589,11 @@ class ES_Browser {
1589
  * @return boolean True if it detects the version correctly otherwise false
1590
  */
1591
  protected function getChromeVersionOnIos() {
1592
- $aresult = explode('/', stristr($this->_agent, 'CriOS'));
1593
- if (isset($aresult[1])) {
1594
- $aversion = explode(' ', $aresult[1]);
1595
- $this->setVersion($aversion[0]);
1596
- $this->setBrowser(self::BROWSER_CHROME);
1597
  return true;
1598
  }
1599
  return false;
@@ -1605,13 +1605,13 @@ class ES_Browser {
1605
  * @return boolean True if the browser is iPhone otherwise false
1606
  */
1607
  protected function checkBrowseriPhone() {
1608
- if (stripos($this->_agent, 'iPhone') !== false) {
1609
- $this->setVersion(self::VERSION_UNKNOWN);
1610
- $this->setBrowser(self::BROWSER_IPHONE);
1611
  $this->getSafariVersionOnIos();
1612
  $this->getChromeVersionOnIos();
1613
  $this->checkForFacebookIos();
1614
- $this->setMobile(true);
1615
  return true;
1616
  }
1617
  return false;
@@ -1623,13 +1623,13 @@ class ES_Browser {
1623
  * @return boolean True if the browser is iPad otherwise false
1624
  */
1625
  protected function checkBrowseriPad() {
1626
- if (stripos($this->_agent, 'iPad') !== false) {
1627
- $this->setVersion(self::VERSION_UNKNOWN);
1628
- $this->setBrowser(self::BROWSER_IPAD);
1629
  $this->getSafariVersionOnIos();
1630
  $this->getChromeVersionOnIos();
1631
  $this->checkForFacebookIos();
1632
- $this->setTablet(true);
1633
  return true;
1634
  }
1635
  return false;
@@ -1641,13 +1641,13 @@ class ES_Browser {
1641
  * @return boolean True if the browser is iPod otherwise false
1642
  */
1643
  protected function checkBrowseriPod() {
1644
- if (stripos($this->_agent, 'iPod') !== false) {
1645
- $this->setVersion(self::VERSION_UNKNOWN);
1646
- $this->setBrowser(self::BROWSER_IPOD);
1647
  $this->getSafariVersionOnIos();
1648
  $this->getChromeVersionOnIos();
1649
  $this->checkForFacebookIos();
1650
- $this->setMobile(true);
1651
  return true;
1652
  }
1653
  return false;
@@ -1659,20 +1659,20 @@ class ES_Browser {
1659
  * @return boolean True if the browser is Android otherwise false
1660
  */
1661
  protected function checkBrowserAndroid() {
1662
- if (stripos($this->_agent, 'Android') !== false) {
1663
- $aresult = explode(' ', stristr($this->_agent, 'Android'));
1664
- if (isset($aresult[1])) {
1665
- $aversion = explode(' ', $aresult[1]);
1666
- $this->setVersion($aversion[0]);
1667
  } else {
1668
- $this->setVersion(self::VERSION_UNKNOWN);
1669
  }
1670
- if (stripos($this->_agent, 'Mobile') !== false) {
1671
- $this->setMobile(true);
1672
  } else {
1673
- $this->setTablet(true);
1674
  }
1675
- $this->setBrowser(self::BROWSER_ANDROID);
1676
  return true;
1677
  }
1678
  return false;
@@ -1684,12 +1684,12 @@ class ES_Browser {
1684
  * @return boolean True if the browser is Vivaldi otherwise false
1685
  */
1686
  protected function checkBrowserVivaldi() {
1687
- if (stripos($this->_agent, 'Vivaldi') !== false) {
1688
- $aresult = explode('/', stristr($this->_agent, 'Vivaldi'));
1689
- if (isset($aresult[1])) {
1690
- $aversion = explode(' ', $aresult[1]);
1691
- $this->setVersion($aversion[0]);
1692
- $this->setBrowser(self::BROWSER_VIVALDI);
1693
  return true;
1694
  }
1695
  }
@@ -1702,19 +1702,19 @@ class ES_Browser {
1702
  * @return boolean True if the browser is Yandex otherwise false
1703
  */
1704
  protected function checkBrowserYandex() {
1705
- if (stripos($this->_agent, 'YaBrowser') !== false) {
1706
- $aresult = explode('/', stristr($this->_agent, 'YaBrowser'));
1707
- if (isset($aresult[1])) {
1708
- $aversion = explode(' ', $aresult[1]);
1709
- $this->setVersion($aversion[0]);
1710
- $this->setBrowser(self::BROWSER_YANDEX);
1711
-
1712
- if (stripos($this->_agent, 'iPad') !== false) {
1713
- $this->setTablet(true);
1714
- } elseif (stripos($this->_agent, 'Mobile') !== false) {
1715
- $this->setMobile(true);
1716
- } elseif (stripos($this->_agent, 'Android') !== false) {
1717
- $this->setTablet(true);
1718
  }
1719
 
1720
  return true;
@@ -1730,14 +1730,14 @@ class ES_Browser {
1730
  * @return boolean True if the browser is PlayStation otherwise false
1731
  */
1732
  protected function checkBrowserPlayStation() {
1733
- if (stripos($this->_agent, 'PlayStation ') !== false) {
1734
- $aresult = explode(' ', stristr($this->_agent, 'PlayStation '));
1735
- $this->setBrowser(self::BROWSER_PLAYSTATION);
1736
- if (isset($aresult[0])) {
1737
- $aversion = explode(')', $aresult[2]);
1738
- $this->setVersion($aversion[0]);
1739
- if (stripos($this->_agent, 'Portable)') !== false || stripos($this->_agent, 'Vita') !== false) {
1740
- $this->setMobile(true);
1741
  }
1742
  return true;
1743
  }
@@ -1751,9 +1751,9 @@ class ES_Browser {
1751
  * @return boolean True if the browser is Wget otherwise false
1752
  */
1753
  protected function checkBrowserWget() {
1754
- if (preg_match('!^Wget/([^ ]+)!i', $this->_agent, $aresult)) {
1755
- $this->setVersion($aresult[1]);
1756
- $this->setBrowser(self::BROWSER_WGET);
1757
  return true;
1758
  }
1759
  return false;
@@ -1764,12 +1764,12 @@ class ES_Browser {
1764
  * @return boolean True if the browser is cURL otherwise false
1765
  */
1766
  protected function checkBrowserCurl() {
1767
- if (strpos($this->_agent, 'curl') === 0) {
1768
- $aresult = explode('/', stristr($this->_agent, 'curl'));
1769
- if (isset($aresult[1])) {
1770
- $aversion = explode(' ', $aresult[1]);
1771
- $this->setVersion($aversion[0]);
1772
- $this->setBrowser(self::BROWSER_CURL);
1773
  return true;
1774
  }
1775
  }
@@ -1780,61 +1780,61 @@ class ES_Browser {
1780
  * Determine the user's platform (last updated 2.0)
1781
  */
1782
  protected function checkPlatform() {
1783
- if (stripos($this->_agent, 'windows') !== false) {
1784
  $this->_platform = self::PLATFORM_WINDOWS;
1785
- } elseif (stripos($this->_agent, 'iPad') !== false) {
1786
  $this->_platform = self::PLATFORM_IPAD;
1787
- } elseif (stripos($this->_agent, 'iPod') !== false) {
1788
  $this->_platform = self::PLATFORM_IPOD;
1789
- } elseif (stripos($this->_agent, 'iPhone') !== false) {
1790
  $this->_platform = self::PLATFORM_IPHONE;
1791
- } elseif (stripos($this->_agent, 'mac') !== false) {
1792
  $this->_platform = self::PLATFORM_APPLE;
1793
- } elseif (stripos($this->_agent, 'android') !== false) {
1794
  $this->_platform = self::PLATFORM_ANDROID;
1795
- } elseif (stripos($this->_agent, 'Silk') !== false) {
1796
  $this->_platform = self::PLATFORM_FIRE_OS;
1797
- } elseif (stripos($this->_agent, 'linux') !== false && stripos($this->_agent, 'SMART-TV') !== false) {
1798
  $this->_platform = self::PLATFORM_LINUX . '/' . self::PLATFORM_SMART_TV;
1799
- } elseif (stripos($this->_agent, 'linux') !== false) {
1800
  $this->_platform = self::PLATFORM_LINUX;
1801
- } elseif (stripos($this->_agent, 'Nokia') !== false) {
1802
  $this->_platform = self::PLATFORM_NOKIA;
1803
- } elseif (stripos($this->_agent, 'BlackBerry') !== false) {
1804
  $this->_platform = self::PLATFORM_BLACKBERRY;
1805
- } elseif (stripos($this->_agent, 'FreeBSD') !== false) {
1806
  $this->_platform = self::PLATFORM_FREEBSD;
1807
- } elseif (stripos($this->_agent, 'OpenBSD') !== false) {
1808
  $this->_platform = self::PLATFORM_OPENBSD;
1809
- } elseif (stripos($this->_agent, 'NetBSD') !== false) {
1810
  $this->_platform = self::PLATFORM_NETBSD;
1811
- } elseif (stripos($this->_agent, 'OpenSolaris') !== false) {
1812
  $this->_platform = self::PLATFORM_OPENSOLARIS;
1813
- } elseif (stripos($this->_agent, 'SunOS') !== false) {
1814
  $this->_platform = self::PLATFORM_SUNOS;
1815
- } elseif (stripos($this->_agent, 'OS\/2') !== false) {
1816
  $this->_platform = self::PLATFORM_OS2;
1817
- } elseif (stripos($this->_agent, 'BeOS') !== false) {
1818
  $this->_platform = self::PLATFORM_BEOS;
1819
- } elseif (stripos($this->_agent, 'win') !== false) {
1820
  $this->_platform = self::PLATFORM_WINDOWS;
1821
- } elseif (stripos($this->_agent, 'Playstation') !== false) {
1822
  $this->_platform = self::PLATFORM_PLAYSTATION;
1823
- } elseif (stripos($this->_agent, 'Roku') !== false) {
1824
  $this->_platform = self::PLATFORM_ROKU;
1825
- } elseif (stripos($this->_agent, 'iOS') !== false) {
1826
  $this->_platform = self::PLATFORM_IPHONE . '/' . self::PLATFORM_IPAD;
1827
- } elseif (stripos($this->_agent, 'tvOS') !== false) {
1828
  $this->_platform = self::PLATFORM_APPLE_TV;
1829
- } elseif (stripos($this->_agent, 'curl') !== false) {
1830
  $this->_platform = self::PLATFORM_TERMINAL;
1831
- } elseif (stripos($this->_agent, 'CrOS') !== false) {
1832
  $this->_platform = self::PLATFORM_CHROME_OS;
1833
- } elseif (stripos($this->_agent, 'okhttp') !== false) {
1834
  $this->_platform = self::PLATFORM_JAVA_ANDROID;
1835
- } elseif (stripos($this->_agent, 'PostmanRuntime') !== false) {
1836
  $this->_platform = self::PLATFORM_POSTMAN;
1837
- } elseif (stripos($this->_agent, 'Iframely') !== false) {
1838
  $this->_platform = self::PLATFORM_I_FRAME;
1839
  }
1840
  }
162
  *
163
  * @param string $userAgent
164
  */
165
+ public function __construct( $userAgent = '' ) {
166
  if ( '' != $userAgent ) {
167
+ $this->setUserAgent( $userAgent );
168
  } else {
169
  $this->reset();
170
  $this->determine();
175
  * Reset all properties
176
  */
177
  public function reset() {
178
+ $this->_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) : '';
179
  $this->_browser_name = self::BROWSER_UNKNOWN;
180
  $this->_version = self::VERSION_UNKNOWN;
181
  $this->_platform = self::PLATFORM_UNKNOWN;
194
  * @param string $browserName
195
  * @return bool True if the browser is the specified browser
196
  */
197
+ public function isBrowser( $browserName ) {
198
+ return ( 0 == strcasecmp( $this->_browser_name, trim( $browserName ) ) );
199
  }
200
 
201
  /**
212
  *
213
  * @param $browser string The name of the Browser
214
  */
215
+ public function setBrowser( $browser ) {
216
  $this->_browser_name = $browser;
217
  }
218
 
230
  *
231
  * @param string $platform The name of the Platform
232
  */
233
+ public function setPlatform( $platform ) {
234
  $this->_platform = $platform;
235
  }
236
 
248
  *
249
  * @param string $version The version of the Browser
250
  */
251
+ public function setVersion( $version ) {
252
+ $this->_version = preg_replace( '/[^0-9,.,a-z,A-Z-]/', '', $version );
253
  }
254
 
255
  /**
266
  *
267
  * @param string $version The version of AOL
268
  */
269
+ public function setAolVersion( $version ) {
270
+ $this->_aol_version = preg_replace( '/[^0-9,.,a-z,A-Z]/', '', $version );
271
  }
272
 
273
  /**
320
  *
321
  * @param $isAol
322
  */
323
+ public function setAol( $isAol ) {
324
  $this->_is_aol = $isAol;
325
  }
326
 
329
  *
330
  * @param boolean $value is the browser a mobile browser or not
331
  */
332
+ protected function setMobile( $value = true ) {
333
  $this->_is_mobile = $value;
334
  }
335
 
338
  *
339
  * @param boolean $value is the browser a tablet browser or not
340
  */
341
+ protected function setTablet( $value = true ) {
342
  $this->_is_tablet = $value;
343
  }
344
 
347
  *
348
  * @param boolean $value is the browser a robot or not
349
  */
350
+ protected function setRobot( $value = true ) {
351
  $this->_is_robot = $value;
352
  }
353
 
356
  *
357
  * @param boolean $value is the browser a robot or not
358
  */
359
+ protected function setFacebook( $value = true ) {
360
  $this->_is_facebook = $value;
361
  }
362
 
374
  *
375
  * @param string $agent_string The value for the User Agent
376
  */
377
+ public function setUserAgent( $agent_string ) {
378
  $this->reset();
379
  $this->_agent = $agent_string;
380
  $this->determine();
387
  * @return boolean True if the browser is using chromeframe
388
  */
389
  public function isChromeFrame() {
390
+ return ( strpos( $this->_agent, 'chromeframe' ) !== false );
391
  }
392
 
393
  /**
421
  // well-known, well-used
422
  // Special Notes:
423
  // (1) Opera must be checked before FireFox due to the odd
424
+ // user agents used in some older versions of Opera
425
  // (2) WebTV is strapped onto Internet Explorer so we must
426
+ // check for WebTV before IE
427
  // (3) (deprecated) Galeon is based on Firefox and needs to be
428
+ // tested before Firefox is tested
429
  // (4) OmniWeb is based on Safari so OmniWeb check must occur
430
+ // before Safari
431
  // (5) Netscape 9+ is based on Firefox so Netscape checks
432
+ // before FireFox are necessary
433
  // (6) Vivaldi is UA contains both Firefox and Chrome so Vivaldi checks
434
+ // before Firefox and Chrome
435
  $this->checkBrowserWebTv() ||
436
  $this->checkBrowserBrave() ||
437
  $this->checkBrowserUCBrowser() ||
509
  * @return boolean True if the browser is the BlackBerry browser otherwise false
510
  */
511
  protected function checkBrowserBlackBerry() {
512
+ if ( stripos( $this->_agent, 'blackberry' ) !== false ) {
513
+ $aresult = explode( '/', stristr( $this->_agent, 'BlackBerry' ) );
514
+ if ( isset( $aresult[1] ) ) {
515
+ $aversion = explode( ' ', $aresult[1] );
516
+ $this->setVersion( $aversion[0] );
517
  $this->_browser_name = self::BROWSER_BLACKBERRY;
518
+ $this->setMobile( true );
519
  return true;
520
  }
521
  }
528
  * @return boolean True if the browser is from AOL otherwise false
529
  */
530
  protected function checkForAol() {
531
+ $this->setAol( false );
532
+ $this->setAolVersion( self::VERSION_UNKNOWN );
533
+
534
+ if ( stripos( $this->_agent, 'aol' ) !== false ) {
535
+ $aversion = explode( ' ', stristr( $this->_agent, 'AOL' ) );
536
+ if ( isset( $aversion[1] ) ) {
537
+ $this->setAol( true );
538
+ $this->setAolVersion( preg_replace( '/[^0-9\.a-z]/i', '', $aversion[1] ) );
539
  return true;
540
  }
541
  }
548
  * @return boolean True if the browser is the GoogletBot otherwise false
549
  */
550
  protected function checkBrowserGoogleBot() {
551
+ if ( stripos( $this->_agent, 'googlebot' ) !== false ) {
552
+ $aresult = explode( '/', stristr( $this->_agent, 'googlebot' ) );
553
+ if ( isset( $aresult[1] ) ) {
554
+ $aversion = explode( ' ', $aresult[1] );
555
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
556
  $this->_browser_name = self::BROWSER_GOOGLEBOT;
557
+ $this->setRobot( true );
558
  return true;
559
  }
560
  }
567
  * @return boolean True if the browser is the YandexBot otherwise false
568
  */
569
  protected function checkBrowserYandexBot() {
570
+ if ( stripos( $this->_agent, 'YandexBot' ) !== false ) {
571
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexBot' ) );
572
+ if ( isset( $aresult[1] ) ) {
573
+ $aversion = explode( ' ', $aresult[1] );
574
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
575
  $this->_browser_name = self::BROWSER_YANDEXBOT;
576
+ $this->setRobot( true );
577
  return true;
578
  }
579
  }
586
  * @return boolean True if the browser is the YandexImageResizer otherwise false
587
  */
588
  protected function checkBrowserYandexImageResizerBot() {
589
+ if ( stripos( $this->_agent, 'YandexImageResizer' ) !== false ) {
590
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexImageResizer' ) );
591
+ if ( isset( $aresult[1] ) ) {
592
+ $aversion = explode( ' ', $aresult[1] );
593
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
594
  $this->_browser_name = self::BROWSER_YANDEXIMAGERESIZER_BOT;
595
+ $this->setRobot( true );
596
  return true;
597
  }
598
  }
605
  * @return boolean True if the browser is the YandexCatalog otherwise false
606
  */
607
  protected function checkBrowserYandexCatalogBot() {
608
+ if ( stripos( $this->_agent, 'YandexCatalog' ) !== false ) {
609
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexCatalog' ) );
610
+ if ( isset( $aresult[1] ) ) {
611
+ $aversion = explode( ' ', $aresult[1] );
612
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
613
  $this->_browser_name = self::BROWSER_YANDEXCATALOG_BOT;
614
+ $this->setRobot( true );
615
  return true;
616
  }
617
  }
624
  * @return boolean True if the browser is the YandexNews otherwise false
625
  */
626
  protected function checkBrowserYandexNewsBot() {
627
+ if ( stripos( $this->_agent, 'YandexNews' ) !== false ) {
628
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexNews' ) );
629
+ if ( isset( $aresult[1] ) ) {
630
+ $aversion = explode( ' ', $aresult[1] );
631
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
632
  $this->_browser_name = self::BROWSER_YANDEXNEWS_BOT;
633
+ $this->setRobot( true );
634
  return true;
635
  }
636
  }
643
  * @return boolean True if the browser is the YandexMetrika otherwise false
644
  */
645
  protected function checkBrowserYandexMetrikaBot() {
646
+ if ( stripos( $this->_agent, 'YandexMetrika' ) !== false ) {
647
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexMetrika' ) );
648
+ if ( isset( $aresult[1] ) ) {
649
+ $aversion = explode( ' ', $aresult[1] );
650
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
651
  $this->_browser_name = self::BROWSER_YANDEXMETRIKA_BOT;
652
+ $this->setRobot( true );
653
  return true;
654
  }
655
  }
662
  * @return boolean True if the browser is the YandexDirect otherwise false
663
  */
664
  protected function checkBrowserYandexDirectBot() {
665
+ if ( stripos( $this->_agent, 'YandexDirect' ) !== false ) {
666
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexDirect' ) );
667
+ if ( isset( $aresult[1] ) ) {
668
+ $aversion = explode( ' ', $aresult[1] );
669
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
670
  $this->_browser_name = self::BROWSER_YANDEXDIRECT_BOT;
671
+ $this->setRobot( true );
672
  return true;
673
  }
674
  }
681
  * @return boolean True if the browser is the YandexWebmaster otherwise false
682
  */
683
  protected function checkBrowserYandexWebmasterBot() {
684
+ if ( stripos( $this->_agent, 'YandexWebmaster' ) !== false ) {
685
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexWebmaster' ) );
686
+ if ( isset( $aresult[1] ) ) {
687
+ $aversion = explode( ' ', $aresult[1] );
688
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
689
  $this->_browser_name = self::BROWSER_YANDEXWEBMASTER_BOT;
690
+ $this->setRobot( true );
691
  return true;
692
  }
693
  }
700
  * @return boolean True if the browser is the YandexFavicons otherwise false
701
  */
702
  protected function checkBrowserYandexFaviconsBot() {
703
+ if ( stripos( $this->_agent, 'YandexFavicons' ) !== false ) {
704
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexFavicons' ) );
705
+ if ( isset( $aresult[1] ) ) {
706
+ $aversion = explode( ' ', $aresult[1] );
707
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
708
  $this->_browser_name = self::BROWSER_YANDEXFAVICONS_BOT;
709
+ $this->setRobot( true );
710
  return true;
711
  }
712
  }
719
  * @return boolean True if the browser is the YandexBlogs otherwise false
720
  */
721
  protected function checkBrowserYandexBlogsBot() {
722
+ if ( stripos( $this->_agent, 'YandexBlogs' ) !== false ) {
723
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexBlogs' ) );
724
+ if ( isset( $aresult[1] ) ) {
725
+ $aversion = explode( ' ', $aresult[1] );
726
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
727
  $this->_browser_name = self::BROWSER_YANDEXBLOGS_BOT;
728
+ $this->setRobot( true );
729
  return true;
730
  }
731
  }
738
  * @return boolean True if the browser is the YandexMedia otherwise false
739
  */
740
  protected function checkBrowserYandexMediaBot() {
741
+ if ( stripos( $this->_agent, 'YandexMedia' ) !== false ) {
742
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexMedia' ) );
743
+ if ( isset( $aresult[1] ) ) {
744
+ $aversion = explode( ' ', $aresult[1] );
745
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
746
  $this->_browser_name = self::BROWSER_YANDEXMEDIA_BOT;
747
+ $this->setRobot( true );
748
  return true;
749
  }
750
  }
757
  * @return boolean True if the browser is the YandexVideo otherwise false
758
  */
759
  protected function checkBrowserYandexVideoBot() {
760
+ if ( stripos( $this->_agent, 'YandexVideo' ) !== false ) {
761
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexVideo' ) );
762
+ if ( isset( $aresult[1] ) ) {
763
+ $aversion = explode( ' ', $aresult[1] );
764
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
765
  $this->_browser_name = self::BROWSER_YANDEXVIDEO_BOT;
766
+ $this->setRobot( true );
767
  return true;
768
  }
769
  }
776
  * @return boolean True if the browser is the YandexImages otherwise false
777
  */
778
  protected function checkBrowserYandexImagesBot() {
779
+ if ( stripos( $this->_agent, 'YandexImages' ) !== false ) {
780
+ $aresult = explode( '/', stristr( $this->_agent, 'YandexImages' ) );
781
+ if ( isset( $aresult[1] ) ) {
782
+ $aversion = explode( ' ', $aresult[1] );
783
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
784
  $this->_browser_name = self::BROWSER_YANDEXIMAGES_BOT;
785
+ $this->setRobot( true );
786
  return true;
787
  }
788
  }
795
  * @return boolean True if the browser is the MSNBot otherwise false
796
  */
797
  protected function checkBrowserMSNBot() {
798
+ if ( stripos( $this->_agent, 'msnbot' ) !== false ) {
799
+ $aresult = explode( '/', stristr( $this->_agent, 'msnbot' ) );
800
+ if ( isset( $aresult[1] ) ) {
801
+ $aversion = explode( ' ', $aresult[1] );
802
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
803
  $this->_browser_name = self::BROWSER_MSNBOT;
804
+ $this->setRobot( true );
805
  return true;
806
  }
807
  }
814
  * @return boolean True if the browser is the BingBot otherwise false
815
  */
816
  protected function checkBrowserBingBot() {
817
+ if ( stripos( $this->_agent, 'bingbot' ) !== false ) {
818
+ $aresult = explode( '/', stristr( $this->_agent, 'bingbot' ) );
819
+ if ( isset( $aresult[1] ) ) {
820
+ $aversion = explode( ' ', $aresult[1] );
821
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
822
  $this->_browser_name = self::BROWSER_BINGBOT;
823
+ $this->setRobot( true );
824
  return true;
825
  }
826
  }
833
  * @return boolean True if the browser is the W3C Validator otherwise false
834
  */
835
  protected function checkBrowserW3CValidator() {
836
+ if ( stripos( $this->_agent, 'W3C-checklink' ) !== false ) {
837
+ $aresult = explode( '/', stristr( $this->_agent, 'W3C-checklink' ) );
838
+ if ( isset( $aresult[1] ) ) {
839
+ $aversion = explode( ' ', $aresult[1] );
840
+ $this->setVersion( $aversion[0] );
841
  $this->_browser_name = self::BROWSER_W3CVALIDATOR;
842
  return true;
843
  }
844
+ } elseif ( stripos( $this->_agent, 'W3C_Validator' ) !== false ) {
845
  // Some of the Validator versions do not delineate w/ a slash - add it back in
846
+ $ua = str_replace( 'W3C_Validator ', 'W3C_Validator/', $this->_agent );
847
+ $aresult = explode( '/', stristr( $ua, 'W3C_Validator' ) );
848
+ if ( isset( $aresult[1] ) ) {
849
+ $aversion = explode( ' ', $aresult[1] );
850
+ $this->setVersion( $aversion[0] );
851
  $this->_browser_name = self::BROWSER_W3CVALIDATOR;
852
  return true;
853
  }
854
+ } elseif ( stripos( $this->_agent, 'W3C-mobileOK' ) !== false ) {
855
  $this->_browser_name = self::BROWSER_W3CVALIDATOR;
856
+ $this->setMobile( true );
857
  return true;
858
  }
859
  return false;
865
  * @return boolean True if the browser is the Yahoo! Slurp Robot otherwise false
866
  */
867
  protected function checkBrowserSlurp() {
868
+ if ( stripos( $this->_agent, 'slurp' ) !== false ) {
869
+ $aresult = explode( '/', stristr( $this->_agent, 'Slurp' ) );
870
+ if ( isset( $aresult[1] ) ) {
871
+ $aversion = explode( ' ', $aresult[1] );
872
+ $this->setVersion( $aversion[0] );
873
  $this->_browser_name = self::BROWSER_SLURP;
874
+ $this->setRobot( true );
875
+ $this->setMobile( false );
876
  return true;
877
  }
878
  }
885
  * @return boolean True if the browser is Brave otherwise false
886
  */
887
  protected function checkBrowserBrave() {
888
+ if ( stripos( $this->_agent, 'Brave/' ) !== false ) {
889
+ $aResult = explode( '/', stristr( $this->_agent, 'Brave' ) );
890
+ if ( isset( $aResult[1] ) ) {
891
+ $aversion = explode( ' ', $aResult[1] );
892
+ $this->setVersion( $aversion[0] );
893
+ $this->setBrowser( self::BROWSER_BRAVE );
894
  return true;
895
  }
896
+ } elseif ( stripos( $this->_agent, ' Brave ' ) !== false ) {
897
+ $this->setBrowser( self::BROWSER_BRAVE );
898
  // this version of the UA did not ship with a version marker
899
  // e.g. Mozilla/5.0 (Linux; Android 7.0; SM-G955F Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/68.0.3440.91 Mobile Safari/537.36
900
+ $this->setVersion( '' );
901
  return true;
902
  }
903
  return false;
909
  * @return boolean True if the browser is Edge otherwise false
910
  */
911
  protected function checkBrowserEdge() {
912
+ $short_edg = stripos( $this->_agent, 'Edg/' ) !== false || stripos( $this->_agent, 'EdgA/' ) !== false ? 'Edg' : false;
913
+ $name = stripos( $this->_agent, 'Edge/' ) !== false ? 'Edge' : $short_edg;
914
  if ( $name ) {
915
+ $aresult = explode( '/', stristr( $this->_agent, $name ) );
916
+ if ( isset( $aresult[1] ) ) {
917
+ $aversion = explode( ' ', $aresult[1] );
918
+ $this->setVersion( $aversion[0] );
919
+ $this->setBrowser( self::BROWSER_EDGE );
920
+ if ( stripos( $this->_agent, 'Windows Phone' ) !== false || stripos( $this->_agent, 'Android' ) !== false ) {
921
+ $this->setMobile( true );
922
  }
923
  return true;
924
  }
932
  * @return boolean True if the browser is Internet Explorer otherwise false
933
  */
934
  protected function checkBrowserInternetExplorer() {
935
+ // Test for IE11
936
+ if ( stripos( $this->_agent, 'Trident/7.0; rv:11.0' ) !== false ) {
937
+ $this->setBrowser( self::BROWSER_IE );
938
+ $this->setVersion( '11.0' );
939
  return true;
940
+ } elseif ( stripos( $this->_agent, 'microsoft internet explorer' ) !== false ) {
941
  // Test for v1 - v1.5 IE
942
+ $this->setBrowser( self::BROWSER_IE );
943
+ $this->setVersion( '1.0' );
944
+ $aresult = stristr( $this->_agent, '/' );
945
+ if ( preg_match( '/308|425|426|474|0b1/i', $aresult ) ) {
946
+ $this->setVersion( '1.5' );
947
  }
948
  return true;
949
+ } elseif ( stripos( $this->_agent, 'msie' ) !== false && stripos( $this->_agent, 'opera' ) === false ) {
950
  // Test for versions > 1.5
951
  // See if the browser is the odd MSN Explorer
952
+ if ( stripos( $this->_agent, 'msnb' ) !== false ) {
953
+ $aresult = explode( ' ', stristr( str_replace( ';', '; ', $this->_agent ), 'MSN' ) );
954
+ if ( isset( $aresult[1] ) ) {
955
+ $this->setBrowser( self::BROWSER_MSN );
956
+ $this->setVersion( str_replace( array( '(', ')', ';' ), '', $aresult[1] ) );
957
  return true;
958
  }
959
  }
960
+ $aresult = explode( ' ', stristr( str_replace( ';', '; ', $this->_agent ), 'msie' ) );
961
+ if ( isset( $aresult[1] ) ) {
962
+ $this->setBrowser( self::BROWSER_IE );
963
+ $this->setVersion( str_replace( array( '(', ')', ';' ), '', $aresult[1] ) );
964
+ if ( stripos( $this->_agent, 'IEMobile' ) !== false ) {
965
+ $this->setBrowser( self::BROWSER_POCKET_IE );
966
+ $this->setMobile( true );
967
  }
968
  return true;
969
  }
970
+ } elseif ( stripos( $this->_agent, 'trident' ) !== false ) {
971
  // Test for versions > IE 10
972
+ $this->setBrowser( self::BROWSER_IE );
973
+ $result = explode( 'rv:', $this->_agent );
974
+ if ( isset( $result[1] ) ) {
975
+ $this->setVersion( preg_replace( '/[^0-9.]+/', '', $result[1] ) );
976
+ $this->_agent = str_replace( array( 'Mozilla', 'Gecko' ), 'MSIE', $this->_agent );
977
  }
978
+ } elseif ( stripos( $this->_agent, 'mspie' ) !== false || stripos( $this->_agent, 'pocket' ) !== false ) {
979
  // Test for Pocket IE
980
+ $aresult = explode( ' ', stristr( $this->_agent, 'mspie' ) );
981
+ if ( isset( $aresult[1] ) ) {
982
+ $this->setPlatform( self::PLATFORM_WINDOWS_CE );
983
+ $this->setBrowser( self::BROWSER_POCKET_IE );
984
+ $this->setMobile( true );
985
+
986
+ if ( stripos( $this->_agent, 'mspie' ) !== false ) {
987
+ $this->setVersion( $aresult[1] );
988
  } else {
989
+ $aversion = explode( '/', $this->_agent );
990
+ if ( isset( $aversion[1] ) ) {
991
+ $this->setVersion( $aversion[1] );
992
  }
993
  }
994
  return true;
1003
  * @return boolean True if the browser is Opera otherwise false
1004
  */
1005
  protected function checkBrowserOpera() {
1006
+ if ( stripos( $this->_agent, 'opera mini' ) !== false ) {
1007
+ $resultant = stristr( $this->_agent, 'opera mini' );
1008
+ if ( preg_match( '/\//', $resultant ) ) {
1009
+ $aresult = explode( '/', $resultant );
1010
+ if ( isset( $aresult[1] ) ) {
1011
+ $aversion = explode( ' ', $aresult[1] );
1012
+ $this->setVersion( $aversion[0] );
1013
  }
1014
  } else {
1015
+ $aversion = explode( ' ', stristr( $resultant, 'opera mini' ) );
1016
+ if ( isset( $aversion[1] ) ) {
1017
+ $this->setVersion( $aversion[1] );
1018
  }
1019
  }
1020
  $this->_browser_name = self::BROWSER_OPERA_MINI;
1021
+ $this->setMobile( true );
1022
  return true;
1023
+ } elseif ( stripos( $this->_agent, 'opera' ) !== false ) {
1024
+ $resultant = stristr( $this->_agent, 'opera' );
1025
+ if ( preg_match( '/Version\/(1*.*)$/', $resultant, $matches ) ) {
1026
+ $this->setVersion( $matches[1] );
1027
+ } elseif ( preg_match( '/\//', $resultant ) ) {
1028
+ $aresult = explode( '/', str_replace( '(', ' ', $resultant ) );
1029
+ if ( isset( $aresult[1] ) ) {
1030
+ $aversion = explode( ' ', $aresult[1] );
1031
+ $this->setVersion( $aversion[0] );
1032
  }
1033
  } else {
1034
+ $aversion = explode( ' ', stristr( $resultant, 'opera' ) );
1035
+ $this->setVersion( isset( $aversion[1] ) ? $aversion[1] : '' );
1036
  }
1037
+ if ( stripos( $this->_agent, 'Opera Mobi' ) !== false ) {
1038
+ $this->setMobile( true );
1039
  }
1040
  $this->_browser_name = self::BROWSER_OPERA;
1041
  return true;
1042
+ } elseif ( stripos( $this->_agent, 'OPR' ) !== false ) {
1043
+ $resultant = stristr( $this->_agent, 'OPR' );
1044
+ if ( preg_match( '/\//', $resultant ) ) {
1045
+ $aresult = explode( '/', str_replace( '(', ' ', $resultant ) );
1046
+ if ( isset( $aresult[1] ) ) {
1047
+ $aversion = explode( ' ', $aresult[1] );
1048
+ $this->setVersion( $aversion[0] );
1049
  }
1050
  }
1051
+ if ( stripos( $this->_agent, 'Mobile' ) !== false ) {
1052
+ $this->setMobile( true );
1053
  }
1054
  $this->_browser_name = self::BROWSER_OPERA;
1055
  return true;
1063
  * @return boolean True if the browser is Chrome otherwise false
1064
  */
1065
  protected function checkBrowserChrome() {
1066
+ if ( stripos( $this->_agent, 'Chrome' ) !== false ) {
1067
+ $aresult = preg_split( '/[\/;]+/', stristr( $this->_agent, 'Chrome' ) );
1068
+ if ( isset( $aresult[1] ) ) {
1069
+ $aversion = explode( ' ', $aresult[1] );
1070
+ $this->setVersion( $aversion[0] );
1071
+ $this->setBrowser( self::BROWSER_CHROME );
1072
+ // Chrome on Android
1073
+ if ( stripos( $this->_agent, 'Android' ) !== false ) {
1074
+ if ( stripos( $this->_agent, 'Mobile' ) !== false ) {
1075
+ $this->setMobile( true );
1076
  } else {
1077
+ $this->setTablet( true );
1078
  }
1079
  }
1080
  return true;
1090
  * @return boolean True if the browser is WebTv otherwise false
1091
  */
1092
  protected function checkBrowserWebTv() {
1093
+ if ( stripos( $this->_agent, 'webtv' ) !== false ) {
1094
+ $aresult = explode( '/', stristr( $this->_agent, 'webtv' ) );
1095
+ if ( isset( $aresult[1] ) ) {
1096
+ $aversion = explode( ' ', $aresult[1] );
1097
+ $this->setVersion( $aversion[0] );
1098
+ $this->setBrowser( self::BROWSER_WEBTV );
1099
  return true;
1100
  }
1101
  }
1108
  * @return boolean True if the browser is NetPositive otherwise false
1109
  */
1110
  protected function checkBrowserNetPositive() {
1111
+ if ( stripos( $this->_agent, 'NetPositive' ) !== false ) {
1112
+ $aresult = explode( '/', stristr( $this->_agent, 'NetPositive' ) );
1113
+ if ( isset( $aresult[1] ) ) {
1114
+ $aversion = explode( ' ', $aresult[1] );
1115
+ $this->setVersion( str_replace( array( '(', ')', ';' ), '', $aversion[0] ) );
1116
+ $this->setBrowser( self::BROWSER_NETPOSITIVE );
1117
  return true;
1118
  }
1119
  }
1126
  * @return boolean True if the browser is Galeon otherwise false
1127
  */
1128
  protected function checkBrowserGaleon() {
1129
+ if ( stripos( $this->_agent, 'galeon' ) !== false ) {
1130
+ $aresult = explode( ' ', stristr( $this->_agent, 'galeon' ) );
1131
+ $aversion = explode( '/', $aresult[0] );
1132
+ if ( isset( $aversion[1] ) ) {
1133
+ $this->setVersion( $aversion[1] );
1134
+ $this->setBrowser( self::BROWSER_GALEON );
1135
  return true;
1136
  }
1137
  }
1144
  * @return boolean True if the browser is Konqueror otherwise false
1145
  */
1146
  protected function checkBrowserKonqueror() {
1147
+ if ( stripos( $this->_agent, 'Konqueror' ) !== false ) {
1148
+ $aresult = explode( ' ', stristr( $this->_agent, 'Konqueror' ) );
1149
+ $aversion = explode( '/', $aresult[0] );
1150
+ if ( isset( $aversion[1] ) ) {
1151
+ $this->setVersion( $aversion[1] );
1152
+ $this->setBrowser( self::BROWSER_KONQUEROR );
1153
  return true;
1154
  }
1155
  }
1162
  * @return boolean True if the browser is iCab otherwise false
1163
  */
1164
  protected function checkBrowserIcab() {
1165
+ if ( stripos( $this->_agent, 'icab' ) !== false ) {
1166
+ $aversion = explode( ' ', stristr( str_replace( '/', ' ', $this->_agent ), 'icab' ) );
1167
+ if ( isset( $aversion[1] ) ) {
1168
+ $this->setVersion( $aversion[1] );
1169
+ $this->setBrowser( self::BROWSER_ICAB );
1170
  return true;
1171
  }
1172
  }
1179
  * @return boolean True if the browser is OmniWeb otherwise false
1180
  */
1181
  protected function checkBrowserOmniWeb() {
1182
+ if ( stripos( $this->_agent, 'omniweb' ) !== false ) {
1183
+ $aresult = explode( '/', stristr( $this->_agent, 'omniweb' ) );
1184
+ $aversion = explode( ' ', isset( $aresult[1] ) ? $aresult[1] : '' );
1185
+ $this->setVersion( $aversion[0] );
1186
+ $this->setBrowser( self::BROWSER_OMNIWEB );
1187
  return true;
1188
  }
1189
  return false;
1195
  * @return boolean True if the browser is Phoenix otherwise false
1196
  */
1197
  protected function checkBrowserPhoenix() {
1198
+ if ( stripos( $this->_agent, 'Phoenix' ) !== false ) {
1199
+ $aversion = explode( '/', stristr( $this->_agent, 'Phoenix' ) );
1200
+ if ( isset( $aversion[1] ) ) {
1201
+ $this->setVersion( $aversion[1] );
1202
+ $this->setBrowser( self::BROWSER_PHOENIX );
1203
  return true;
1204
  }
1205
  }
1212
  * @return boolean True if the browser is Firebird otherwise false
1213
  */
1214
  protected function checkBrowserFirebird() {
1215
+ if ( stripos( $this->_agent, 'Firebird' ) !== false ) {
1216
+ $aversion = explode( '/', stristr( $this->_agent, 'Firebird' ) );
1217
+ if ( isset( $aversion[1] ) ) {
1218
+ $this->setVersion( $aversion[1] );
1219
+ $this->setBrowser( self::BROWSER_FIREBIRD );
1220
  return true;
1221
  }
1222
  }
1230
  * @return boolean True if the browser is Netscape Navigator 9+ otherwise false
1231
  */
1232
  protected function checkBrowserNetscapeNavigator9Plus() {
1233
+ if ( stripos( $this->_agent, 'Firefox' ) !== false && preg_match( '/Navigator\/([^ ]*)/i', $this->_agent, $matches ) ) {
1234
+ $this->setVersion( $matches[1] );
1235
+ $this->setBrowser( self::BROWSER_NETSCAPE_NAVIGATOR );
1236
  return true;
1237
+ } elseif ( stripos( $this->_agent, 'Firefox' ) === false && preg_match( '/Netscape6?\/([^ ]*)/i', $this->_agent, $matches ) ) {
1238
+ $this->setVersion( $matches[1] );
1239
+ $this->setBrowser( self::BROWSER_NETSCAPE_NAVIGATOR );
1240
  return true;
1241
  }
1242
  return false;
1248
  * @return boolean True if the browser is Shiretoko otherwise false
1249
  */
1250
  protected function checkBrowserShiretoko() {
1251
+ if ( stripos( $this->_agent, 'Mozilla' ) !== false && preg_match( '/Shiretoko\/([^ ]*)/i', $this->_agent, $matches ) ) {
1252
+ $this->setVersion( $matches[1] );
1253
+ $this->setBrowser( self::BROWSER_SHIRETOKO );
1254
  return true;
1255
  }
1256
  return false;
1262
  * @return boolean True if the browser is Ice Cat otherwise false
1263
  */
1264
  protected function checkBrowserIceCat() {
1265
+ if ( stripos( $this->_agent, 'Mozilla' ) !== false && preg_match( '/IceCat\/([^ ]*)/i', $this->_agent, $matches ) ) {
1266
+ $this->setVersion( $matches[1] );
1267
+ $this->setBrowser( self::BROWSER_ICECAT );
1268
  return true;
1269
  }
1270
  return false;
1276
  * @return boolean True if the browser is Nokia otherwise false
1277
  */
1278
  protected function checkBrowserNokia() {
1279
+ if ( preg_match( '/Nokia([^\/]+)\/([^ SP]+)/i', $this->_agent, $matches ) ) {
1280
+ $this->setVersion( $matches[2] );
1281
+ if ( stripos( $this->_agent, 'Series60' ) !== false || strpos( $this->_agent, 'S60' ) !== false ) {
1282
+ $this->setBrowser( self::BROWSER_NOKIA_S60 );
1283
  } else {
1284
+ $this->setBrowser( self::BROWSER_NOKIA );
1285
  }
1286
+ $this->setMobile( true );
1287
  return true;
1288
  }
1289
  return false;
1295
  * @return boolean True if the browser is Palemoon otherwise false
1296
  */
1297
  protected function checkBrowserPalemoon() {
1298
+ if ( stripos( $this->_agent, 'safari' ) === false ) {
1299
+ if ( preg_match( '/Palemoon[\/ \(]([^ ;\)]+)/i', $this->_agent, $matches ) ) {
1300
+ $this->setVersion( $matches[1] );
1301
+ $this->setBrowser( self::BROWSER_PALEMOON );
1302
  return true;
1303
+ } elseif ( preg_match( '/Palemoon([0-9a-zA-Z\.]+)/i', $this->_agent, $matches ) ) {
1304
+ $this->setVersion( $matches[1] );
1305
+ $this->setBrowser( self::BROWSER_PALEMOON );
1306
  return true;
1307
+ } elseif ( preg_match( '/Palemoon/i', $this->_agent, $matches ) ) {
1308
+ $this->setVersion( '' );
1309
+ $this->setBrowser( self::BROWSER_PALEMOON );
1310
  return true;
1311
  }
1312
  }
1319
  * @return boolean True if the browser is UCBrowser otherwise false
1320
  */
1321
  protected function checkBrowserUCBrowser() {
1322
+ if ( preg_match( '/UC ?Browser\/?([\d\.]+)/', $this->_agent, $matches ) ) {
1323
+ if ( isset( $matches[1] ) ) {
1324
+ $this->setVersion( $matches[1] );
1325
  }
1326
+ if ( stripos( $this->_agent, 'Mobile' ) !== false ) {
1327
+ $this->setMobile( true );
1328
  } else {
1329
+ $this->setTablet( true );
1330
  }
1331
+ $this->setBrowser( self::BROWSER_UCBROWSER );
1332
  return true;
1333
  }
1334
  return false;
1340
  * @return boolean True if the browser is Firefox otherwise false
1341
  */
1342
  protected function checkBrowserFirefox() {
1343
+ if ( stripos( $this->_agent, 'safari' ) === false ) {
1344
+ if ( preg_match( '/Firefox[\/ \(]([^ ;\)]+)/i', $this->_agent, $matches ) ) {
1345
+ $this->setVersion( $matches[1] );
1346
+ $this->setBrowser( self::BROWSER_FIREFOX );
1347
+ // Firefox on Android
1348
+ if ( stripos( $this->_agent, 'Android' ) !== false || stripos( $this->_agent, 'iPhone' ) !== false ) {
1349
+ if ( stripos( $this->_agent, 'Mobile' ) !== false || stripos( $this->_agent, 'Tablet' ) !== false ) {
1350
+ $this->setMobile( true );
1351
  } else {
1352
+ $this->setTablet( true );
1353
  }
1354
  }
1355
  return true;
1356
+ } elseif ( preg_match( '/Firefox([0-9a-zA-Z\.]+)/i', $this->_agent, $matches ) ) {
1357
+ $this->setVersion( $matches[1] );
1358
+ $this->setBrowser( self::BROWSER_FIREFOX );
1359
  return true;
1360
+ } elseif ( preg_match( '/Firefox$/i', $this->_agent, $matches ) ) {
1361
+ $this->setVersion( '' );
1362
+ $this->setBrowser( self::BROWSER_FIREFOX );
1363
  return true;
1364
  }
1365
+ } elseif ( preg_match( '/FxiOS[\/ \(]([^ ;\)]+)/i', $this->_agent, $matches ) ) {
1366
+ $this->setVersion( $matches[1] );
1367
+ $this->setBrowser( self::BROWSER_FIREFOX );
1368
+ // Firefox on Android
1369
+ if ( stripos( $this->_agent, 'Android' ) !== false || stripos( $this->_agent, 'iPhone' ) !== false ) {
1370
+ if ( stripos( $this->_agent, 'Mobile' ) !== false || stripos( $this->_agent, 'Tablet' ) !== false ) {
1371
+ $this->setMobile( true );
1372
  } else {
1373
+ $this->setTablet( true );
1374
  }
1375
  }
1376
  return true;
1384
  * @return boolean True if the browser is Firefox otherwise false
1385
  */
1386
  protected function checkBrowserIceweasel() {
1387
+ if ( stripos( $this->_agent, 'Iceweasel' ) !== false ) {
1388
+ $aresult = explode( '/', stristr( $this->_agent, 'Iceweasel' ) );
1389
+ if ( isset( $aresult[1] ) ) {
1390
+ $aversion = explode( ' ', $aresult[1] );
1391
+ $this->setVersion( $aversion[0] );
1392
+ $this->setBrowser( self::BROWSER_ICEWEASEL );
1393
  return true;
1394
  }
1395
  }
1402
  * @return boolean True if the browser is Mozilla otherwise false
1403
  */
1404
  protected function checkBrowserMozilla() {
1405
+ if ( stripos( $this->_agent, 'mozilla' ) !== false && preg_match( '/rv:[0-9].[0-9][a-b]?/i', $this->_agent ) && stripos( $this->_agent, 'netscape' ) === false ) {
1406
+ $aversion = explode( ' ', stristr( $this->_agent, 'rv:' ) );
1407
+ preg_match( '/rv:[0-9].[0-9][a-b]?/i', $this->_agent, $aversion );
1408
+ $this->setVersion( str_replace( 'rv:', '', $aversion[0] ) );
1409
+ $this->setBrowser( self::BROWSER_MOZILLA );
1410
  return true;
1411
+ } elseif ( stripos( $this->_agent, 'mozilla' ) !== false && preg_match( '/rv:[0-9]\.[0-9]/i', $this->_agent ) && stripos( $this->_agent, 'netscape' ) === false ) {
1412
+ $aversion = explode( '', stristr( $this->_agent, 'rv:' ) );
1413
+ $this->setVersion( str_replace( 'rv:', '', $aversion[0] ) );
1414
+ $this->setBrowser( self::BROWSER_MOZILLA );
1415
  return true;
1416
+ } elseif ( stripos( $this->_agent, 'mozilla' ) !== false && preg_match( '/mozilla\/([^ ]*)/i', $this->_agent, $matches ) && stripos( $this->_agent, 'netscape' ) === false ) {
1417
+ $this->setVersion( $matches[1] );
1418
+ $this->setBrowser( self::BROWSER_MOZILLA );
1419
  return true;
1420
  }
1421
  return false;
1427
  * @return boolean True if the browser is Lynx otherwise false
1428
  */
1429
  protected function checkBrowserLynx() {
1430
+ if ( stripos( $this->_agent, 'lynx' ) !== false ) {
1431
+ $aresult = explode( '/', stristr( $this->_agent, 'Lynx' ) );
1432
+ $aversion = explode( ' ', ( isset( $aresult[1] ) ? $aresult[1] : '' ) );
1433
+ $this->setVersion( $aversion[0] );
1434
+ $this->setBrowser( self::BROWSER_LYNX );
1435
  return true;
1436
  }
1437
  return false;
1443
  * @return boolean True if the browser is Amaya otherwise false
1444
  */
1445
  protected function checkBrowserAmaya() {
1446
+ if ( stripos( $this->_agent, 'amaya' ) !== false ) {
1447
+ $aresult = explode( '/', stristr( $this->_agent, 'Amaya' ) );
1448
+ if ( isset( $aresult[1] ) ) {
1449
+ $aversion = explode( ' ', $aresult[1] );
1450
+ $this->setVersion( $aversion[0] );
1451
+ $this->setBrowser( self::BROWSER_AMAYA );
1452
  return true;
1453
  }
1454
  }
1462
  */
1463
  protected function checkBrowserSafari() {
1464
  if (
1465
+ stripos( $this->_agent, 'Safari' ) !== false
1466
+ && stripos( $this->_agent, 'iPhone' ) === false
1467
+ && stripos( $this->_agent, 'iPod' ) === false
1468
  ) {
1469
 
1470
+ $aresult = explode( '/', stristr( $this->_agent, 'Version' ) );
1471
+ if ( isset( $aresult[1] ) ) {
1472
+ $aversion = explode( ' ', $aresult[1] );
1473
+ $this->setVersion( $aversion[0] );
1474
  } else {
1475
+ $this->setVersion( self::VERSION_UNKNOWN );
1476
  }
1477
+ $this->setBrowser( self::BROWSER_SAFARI );
1478
  return true;
1479
  }
1480
  return false;
1481
  }
1482
 
1483
  protected function checkBrowserSamsung() {
1484
+ if ( stripos( $this->_agent, 'SamsungBrowser' ) !== false ) {
1485
 
1486
+ $aresult = explode( '/', stristr( $this->_agent, 'SamsungBrowser' ) );
1487
+ if ( isset( $aresult[1] ) ) {
1488
+ $aversion = explode( ' ', $aresult[1] );
1489
+ $this->setVersion( $aversion[0] );
1490
  } else {
1491
+ $this->setVersion( self::VERSION_UNKNOWN );
1492
  }
1493
+ $this->setBrowser( self::BROWSER_SAMSUNG );
1494
  return true;
1495
  }
1496
  return false;
1497
  }
1498
 
1499
  protected function checkBrowserSilk() {
1500
+ if ( stripos( $this->_agent, 'Silk' ) !== false ) {
1501
+ $aresult = explode( '/', stristr( $this->_agent, 'Silk' ) );
1502
+ if ( isset( $aresult[1] ) ) {
1503
+ $aversion = explode( ' ', $aresult[1] );
1504
+ $this->setVersion( $aversion[0] );
1505
  } else {
1506
+ $this->setVersion( self::VERSION_UNKNOWN );
1507
  }
1508
+ $this->setBrowser( self::BROWSER_SILK );
1509
  return true;
1510
  }
1511
  return false;
1512
  }
1513
 
1514
  protected function checkBrowserIframely() {
1515
+ if ( stripos( $this->_agent, 'Iframely' ) !== false ) {
1516
+ $aresult = explode( '/', stristr( $this->_agent, 'Iframely' ) );
1517
+ if ( isset( $aresult[1] ) ) {
1518
+ $aversion = explode( ' ', $aresult[1] );
1519
+ $this->setVersion( $aversion[0] );
1520
  } else {
1521
+ $this->setVersion( self::VERSION_UNKNOWN );
1522
  }
1523
+ $this->setBrowser( self::BROWSER_I_FRAME );
1524
  return true;
1525
  }
1526
  return false;
1527
  }
1528
 
1529
  protected function checkBrowserCocoa() {
1530
+ if ( stripos( $this->_agent, 'CocoaRestClient' ) !== false ) {
1531
+ $aresult = explode( '/', stristr( $this->_agent, 'CocoaRestClient' ) );
1532
+ if ( isset( $aresult[1] ) ) {
1533
+ $aversion = explode( ' ', $aresult[1] );
1534
+ $this->setVersion( $aversion[0] );
1535
  } else {
1536
+ $this->setVersion( self::VERSION_UNKNOWN );
1537
  }
1538
+ $this->setBrowser( self::BROWSER_COCOA );
1539
  return true;
1540
  }
1541
  return false;
1547
  * @return boolean True if it detects FacebookExternalHit otherwise false
1548
  */
1549
  protected function checkFacebookExternalHit() {
1550
+ if ( stristr( $this->_agent, 'FacebookExternalHit' ) ) {
1551
+ $this->setRobot( true );
1552
+ $this->setFacebook( true );
1553
  return true;
1554
  }
1555
  return false;
1561
  * @return boolean True if it detects internal Facebook browser otherwise false
1562
  */
1563
  protected function checkForFacebookIos() {
1564
+ if ( stristr( $this->_agent, 'FBIOS' ) ) {
1565
+ $this->setFacebook( true );
1566
  return true;
1567
  }
1568
  return false;
1574
  * @return boolean True if it detects the version correctly otherwise false
1575
  */
1576
  protected function getSafariVersionOnIos() {
1577
+ $aresult = explode( '/', stristr( $this->_agent, 'Version' ) );
1578
+ if ( isset( $aresult[1] ) ) {
1579
+ $aversion = explode( ' ', $aresult[1] );
1580
+ $this->setVersion( $aversion[0] );
1581
  return true;
1582
  }
1583
  return false;
1589
  * @return boolean True if it detects the version correctly otherwise false
1590
  */
1591
  protected function getChromeVersionOnIos() {
1592
+ $aresult = explode( '/', stristr( $this->_agent, 'CriOS' ) );
1593
+ if ( isset( $aresult[1] ) ) {
1594
+ $aversion = explode( ' ', $aresult[1] );
1595
+ $this->setVersion( $aversion[0] );
1596
+ $this->setBrowser( self::BROWSER_CHROME );
1597
  return true;
1598
  }
1599
  return false;
1605
  * @return boolean True if the browser is iPhone otherwise false
1606
  */
1607
  protected function checkBrowseriPhone() {
1608
+ if ( stripos( $this->_agent, 'iPhone' ) !== false ) {
1609
+ $this->setVersion( self::VERSION_UNKNOWN );
1610
+ $this->setBrowser( self::BROWSER_IPHONE );
1611
  $this->getSafariVersionOnIos();
1612
  $this->getChromeVersionOnIos();
1613
  $this->checkForFacebookIos();
1614
+ $this->setMobile( true );
1615
  return true;
1616
  }
1617
  return false;
1623
  * @return boolean True if the browser is iPad otherwise false
1624
  */
1625
  protected function checkBrowseriPad() {
1626
+ if ( stripos( $this->_agent, 'iPad' ) !== false ) {
1627
+ $this->setVersion( self::VERSION_UNKNOWN );
1628
+ $this->setBrowser( self::BROWSER_IPAD );
1629
  $this->getSafariVersionOnIos();
1630
  $this->getChromeVersionOnIos();
1631
  $this->checkForFacebookIos();
1632
+ $this->setTablet( true );
1633
  return true;
1634
  }
1635
  return false;
1641
  * @return boolean True if the browser is iPod otherwise false
1642
  */
1643
  protected function checkBrowseriPod() {
1644
+ if ( stripos( $this->_agent, 'iPod' ) !== false ) {
1645
+ $this->setVersion( self::VERSION_UNKNOWN );
1646
+ $this->setBrowser( self::BROWSER_IPOD );
1647
  $this->getSafariVersionOnIos();
1648
  $this->getChromeVersionOnIos();
1649
  $this->checkForFacebookIos();
1650
+ $this->setMobile( true );
1651
  return true;
1652
  }
1653
  return false;
1659
  * @return boolean True if the browser is Android otherwise false
1660
  */
1661
  protected function checkBrowserAndroid() {
1662
+ if ( stripos( $this->_agent, 'Android' ) !== false ) {
1663
+ $aresult = explode( ' ', stristr( $this->_agent, 'Android' ) );
1664
+ if ( isset( $aresult[1] ) ) {
1665
+ $aversion = explode( ' ', $aresult[1] );
1666
+ $this->setVersion( $aversion[0] );
1667
  } else {
1668
+ $this->setVersion( self::VERSION_UNKNOWN );
1669
  }
1670
+ if ( stripos( $this->_agent, 'Mobile' ) !== false ) {
1671
+ $this->setMobile( true );
1672
  } else {
1673
+ $this->setTablet( true );
1674
  }
1675
+ $this->setBrowser( self::BROWSER_ANDROID );
1676
  return true;
1677
  }
1678
  return false;
1684
  * @return boolean True if the browser is Vivaldi otherwise false
1685
  */
1686
  protected function checkBrowserVivaldi() {
1687
+ if ( stripos( $this->_agent, 'Vivaldi' ) !== false ) {
1688
+ $aresult = explode( '/', stristr( $this->_agent, 'Vivaldi' ) );
1689
+ if ( isset( $aresult[1] ) ) {
1690
+ $aversion = explode( ' ', $aresult[1] );
1691
+ $this->setVersion( $aversion[0] );
1692
+ $this->setBrowser( self::BROWSER_VIVALDI );
1693
  return true;
1694
  }
1695
  }
1702
  * @return boolean True if the browser is Yandex otherwise false
1703
  */
1704
  protected function checkBrowserYandex() {
1705
+ if ( stripos( $this->_agent, 'YaBrowser' ) !== false ) {
1706
+ $aresult = explode( '/', stristr( $this->_agent, 'YaBrowser' ) );
1707
+ if ( isset( $aresult[1] ) ) {
1708
+ $aversion = explode( ' ', $aresult[1] );
1709
+ $this->setVersion( $aversion[0] );
1710
+ $this->setBrowser( self::BROWSER_YANDEX );
1711
+
1712
+ if ( stripos( $this->_agent, 'iPad' ) !== false ) {
1713
+ $this->setTablet( true );
1714
+ } elseif ( stripos( $this->_agent, 'Mobile' ) !== false ) {
1715
+ $this->setMobile( true );
1716
+ } elseif ( stripos( $this->_agent, 'Android' ) !== false ) {
1717
+ $this->setTablet( true );
1718
  }
1719
 
1720
  return true;
1730
  * @return boolean True if the browser is PlayStation otherwise false
1731
  */
1732
  protected function checkBrowserPlayStation() {
1733
+ if ( stripos( $this->_agent, 'PlayStation ' ) !== false ) {
1734
+ $aresult = explode( ' ', stristr( $this->_agent, 'PlayStation ' ) );
1735
+ $this->setBrowser( self::BROWSER_PLAYSTATION );
1736
+ if ( isset( $aresult[0] ) ) {
1737
+ $aversion = explode( ')', $aresult[2] );
1738
+ $this->setVersion( $aversion[0] );
1739
+ if ( stripos( $this->_agent, 'Portable)' ) !== false || stripos( $this->_agent, 'Vita' ) !== false ) {
1740
+ $this->setMobile( true );
1741
  }
1742
  return true;
1743
  }
1751
  * @return boolean True if the browser is Wget otherwise false
1752
  */
1753
  protected function checkBrowserWget() {
1754
+ if ( preg_match( '!^Wget/([^ ]+)!i', $this->_agent, $aresult ) ) {
1755
+ $this->setVersion( $aresult[1] );
1756
+ $this->setBrowser( self::BROWSER_WGET );
1757
  return true;
1758
  }
1759
  return false;
1764
  * @return boolean True if the browser is cURL otherwise false
1765
  */
1766
  protected function checkBrowserCurl() {
1767
+ if ( strpos( $this->_agent, 'curl' ) === 0 ) {
1768
+ $aresult = explode( '/', stristr( $this->_agent, 'curl' ) );
1769
+ if ( isset( $aresult[1] ) ) {
1770
+ $aversion = explode( ' ', $aresult[1] );
1771
+ $this->setVersion( $aversion[0] );
1772
+ $this->setBrowser( self::BROWSER_CURL );
1773
  return true;
1774
  }
1775
  }
1780
  * Determine the user's platform (last updated 2.0)
1781
  */
1782
  protected function checkPlatform() {
1783
+ if ( stripos( $this->_agent, 'windows' ) !== false ) {
1784
  $this->_platform = self::PLATFORM_WINDOWS;
1785
+ } elseif ( stripos( $this->_agent, 'iPad' ) !== false ) {
1786
  $this->_platform = self::PLATFORM_IPAD;
1787
+ } elseif ( stripos( $this->_agent, 'iPod' ) !== false ) {
1788
  $this->_platform = self::PLATFORM_IPOD;
1789
+ } elseif ( stripos( $this->_agent, 'iPhone' ) !== false ) {
1790
  $this->_platform = self::PLATFORM_IPHONE;
1791
+ } elseif ( stripos( $this->_agent, 'mac' ) !== false ) {
1792
  $this->_platform = self::PLATFORM_APPLE;
1793
+ } elseif ( stripos( $this->_agent, 'android' ) !== false ) {
1794
  $this->_platform = self::PLATFORM_ANDROID;
1795
+ } elseif ( stripos( $this->_agent, 'Silk' ) !== false ) {
1796
  $this->_platform = self::PLATFORM_FIRE_OS;
1797
+ } elseif ( stripos( $this->_agent, 'linux' ) !== false && stripos( $this->_agent, 'SMART-TV' ) !== false ) {
1798
  $this->_platform = self::PLATFORM_LINUX . '/' . self::PLATFORM_SMART_TV;
1799
+ } elseif ( stripos( $this->_agent, 'linux' ) !== false ) {
1800
  $this->_platform = self::PLATFORM_LINUX;
1801
+ } elseif ( stripos( $this->_agent, 'Nokia' ) !== false ) {
1802
  $this->_platform = self::PLATFORM_NOKIA;
1803
+ } elseif ( stripos( $this->_agent, 'BlackBerry' ) !== false ) {
1804
  $this->_platform = self::PLATFORM_BLACKBERRY;
1805
+ } elseif ( stripos( $this->_agent, 'FreeBSD' ) !== false ) {
1806
  $this->_platform = self::PLATFORM_FREEBSD;
1807
+ } elseif ( stripos( $this->_agent, 'OpenBSD' ) !== false ) {
1808
  $this->_platform = self::PLATFORM_OPENBSD;
1809
+ } elseif ( stripos( $this->_agent, 'NetBSD' ) !== false ) {
1810
  $this->_platform = self::PLATFORM_NETBSD;
1811
+ } elseif ( stripos( $this->_agent, 'OpenSolaris' ) !== false ) {
1812
  $this->_platform = self::PLATFORM_OPENSOLARIS;
1813
+ } elseif ( stripos( $this->_agent, 'SunOS' ) !== false ) {
1814
  $this->_platform = self::PLATFORM_SUNOS;
1815
+ } elseif ( stripos( $this->_agent, 'OS\/2' ) !== false ) {
1816
  $this->_platform = self::PLATFORM_OS2;
1817
+ } elseif ( stripos( $this->_agent, 'BeOS' ) !== false ) {
1818
  $this->_platform = self::PLATFORM_BEOS;
1819
+ } elseif ( stripos( $this->_agent, 'win' ) !== false ) {
1820
  $this->_platform = self::PLATFORM_WINDOWS;
1821
+ } elseif ( stripos( $this->_agent, 'Playstation' ) !== false ) {
1822
  $this->_platform = self::PLATFORM_PLAYSTATION;
1823
+ } elseif ( stripos( $this->_agent, 'Roku' ) !== false ) {
1824
  $this->_platform = self::PLATFORM_ROKU;
1825
+ } elseif ( stripos( $this->_agent, 'iOS' ) !== false ) {
1826
  $this->_platform = self::PLATFORM_IPHONE . '/' . self::PLATFORM_IPAD;
1827
+ } elseif ( stripos( $this->_agent, 'tvOS' ) !== false ) {
1828
  $this->_platform = self::PLATFORM_APPLE_TV;
1829
+ } elseif ( stripos( $this->_agent, 'curl' ) !== false ) {
1830
  $this->_platform = self::PLATFORM_TERMINAL;
1831
+ } elseif ( stripos( $this->_agent, 'CrOS' ) !== false ) {
1832
  $this->_platform = self::PLATFORM_CHROME_OS;
1833
+ } elseif ( stripos( $this->_agent, 'okhttp' ) !== false ) {
1834
  $this->_platform = self::PLATFORM_JAVA_ANDROID;
1835
+ } elseif ( stripos( $this->_agent, 'PostmanRuntime' ) !== false ) {
1836
  $this->_platform = self::PLATFORM_POSTMAN;
1837
+ } elseif ( stripos( $this->_agent, 'Iframely' ) !== false ) {
1838
  $this->_platform = self::PLATFORM_I_FRAME;
1839
  }
1840
  }
lite/includes/classes/class-es-cache.php CHANGED
@@ -22,7 +22,6 @@ if ( ! class_exists( 'ES_Cache' ) ) {
22
  * Cache enabled/disabled
23
  *
24
  * @var bool
25
- *
26
  */
27
  public static $enabled = true;
28
 
@@ -30,7 +29,6 @@ if ( ! class_exists( 'ES_Cache' ) ) {
30
  * Get default transient expiration
31
  *
32
  * @return mixed|void
33
- *
34
  */
35
  public static function get_default_transient_expiration() {
36
  return apply_filters( 'ig_es_cache_default_expiration', 10 );
@@ -41,7 +39,7 @@ if ( ! class_exists( 'ES_Cache' ) ) {
41
  *
42
  * @param $key
43
  * @param $value
44
- * @param bool $expiration
45
  *
46
  * @return bool
47
  */
@@ -88,7 +86,7 @@ if ( ! class_exists( 'ES_Cache' ) ) {
88
  * Only sets if key is not falsy
89
  *
90
  * @param string $key
91
- * @param mixed $value
92
  * @param string $group
93
  *
94
  * @since 4.4.0
@@ -107,7 +105,7 @@ if ( ! class_exists( 'ES_Cache' ) ) {
107
  * @param $key
108
  * @param $group
109
  * @param false $force
110
- * @param null $found
111
  *
112
  * @return false|mixed
113
  */
22
  * Cache enabled/disabled
23
  *
24
  * @var bool
 
25
  */
26
  public static $enabled = true;
27
 
29
  * Get default transient expiration
30
  *
31
  * @return mixed|void
 
32
  */
33
  public static function get_default_transient_expiration() {
34
  return apply_filters( 'ig_es_cache_default_expiration', 10 );
39
  *
40
  * @param $key
41
  * @param $value
42
+ * @param bool $expiration
43
  *
44
  * @return bool
45
  */
86
  * Only sets if key is not falsy
87
  *
88
  * @param string $key
89
+ * @param mixed $value
90
  * @param string $group
91
  *
92
  * @since 4.4.0
105
  * @param $key
106
  * @param $group
107
  * @param false $force
108
+ * @param null $found
109
  *
110
  * @return false|mixed
111
  */
lite/includes/classes/class-es-campaign-report.php CHANGED
@@ -21,7 +21,7 @@ class ES_Campaign_Report extends ES_List_Table {
21
  );
22
 
23
  add_action( 'ig_es_view_activity_table_html', array( $this, 'view_activity_report_table' ), 10, 3 );
24
- add_action( 'admin_footer', array( $this, 'es_view_activity_report_sort_and_filter') );
25
  }
26
 
27
  public function es_campaign_report_callback() {
@@ -29,7 +29,7 @@ class ES_Campaign_Report extends ES_List_Table {
29
 
30
  <?php
31
  $this->ajax_response();
32
- $paged = ig_es_get_request_data( 'paged', 1 );
33
  $campaign_class = '';
34
 
35
  if ( ES()->is_pro() ) {
@@ -51,7 +51,7 @@ class ES_Campaign_Report extends ES_List_Table {
51
  </div>
52
  </div>
53
  </div>
54
- <?php
55
  }
56
 
57
  public function ajax_response() {
@@ -74,17 +74,17 @@ class ES_Campaign_Report extends ES_List_Table {
74
  $headers = ob_get_clean();
75
 
76
  ob_start();
77
- $this->pagination('top');
78
  $pagination_top = ob_get_clean();
79
 
80
  ob_start();
81
- $this->pagination('bottom');
82
  $pagination_bottom = ob_get_clean();
83
 
84
  $response = array( 'rows' => $rows );
85
-
86
- $response['column_headers'] = $headers;
87
- $response['pagination']['top'] = $pagination_top;
88
  $response['pagination']['bottom'] = $pagination_bottom;
89
 
90
  if ( isset( $total_items ) ) {
@@ -93,12 +93,12 @@ class ES_Campaign_Report extends ES_List_Table {
93
  }
94
 
95
  if ( isset( $total_pages ) ) {
96
- $response['total_pages'] = $total_pages;
97
  $response['total_pages_i18n'] = number_format_i18n( $total_pages );
98
  }
99
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
100
- die( json_encode( $response ));
101
-
102
  } else {
103
  return $response;
104
  }
@@ -112,50 +112,50 @@ class ES_Campaign_Report extends ES_List_Table {
112
  public function get_sortable_columns() {
113
 
114
  $sortable_columns = array(
115
- 'email' => array( 'email', false ),
116
- 'country_flag' => array( 'country_flag', false ),
117
- 'os' => array( 'os', false ),
118
- 'email_client' => array( 'email_client', false ),
119
- 'sent_at' => array( 'sent_at', false ),
120
- 'opened_at' => array( 'opened_at', false ),
121
- 'status' => array( 'status', false ),
122
  );
123
 
124
  return $sortable_columns;
125
  }
126
-
127
 
128
  /**
129
  * Handles data query and filter, sorting, and pagination.
130
  */
131
  public function prepare_items() {
132
-
133
  $per_page = 100;
134
  $columns = $this->get_columns();
135
  $hidden = array();
136
  $sortable = $this->get_sortable_columns();
137
-
138
- $this->_column_headers = array($columns, $hidden, $sortable);
139
-
140
  $data = $this->get_activity_table_data();
141
  $total_items = $this->get_activity_table_data( true );
142
 
143
  $this->items = $data;
144
-
145
  /**
146
  * Call to _set_pagination_args method for informations about
147
  * total items, items for page, total pages and ordering
148
  */
149
  $this->set_pagination_args(
150
  array(
151
- 'total_items' => $total_items,
152
- 'per_page' => $per_page,
153
  )
154
  );
155
  }
156
 
157
  /**
158
- * Method to handle display of WP_List table
159
  *
160
  * @Override of display method
161
  */
@@ -174,10 +174,10 @@ class ES_Campaign_Report extends ES_List_Table {
174
  * @since 4.6.12
175
  */
176
  public function search_box( $text = '', $input_id = '' ) {
177
- do_action( 'ig_es_campaign_reports_filter_options', $text, $input_id );
178
  }
179
 
180
-
181
  /**
182
  * Associative array of columns
183
  *
@@ -185,12 +185,12 @@ class ES_Campaign_Report extends ES_List_Table {
185
  */
186
  public function get_columns() {
187
  $columns = array(
188
- 'sr_no' => '#',
189
- 'email' => __( 'Email', 'email-subscribers' ),
190
- 'status' => __( 'Status', 'email-subscribers' ),
191
- 'sent_at' => __( 'Sent Date', 'email-subscribers' ),
192
- 'opened_at' => __( 'Viewed Date', 'email-subscribers' ),
193
-
194
  );
195
 
196
  $columns = apply_filters( 'additional_es_campaign_report_columns', $columns );
@@ -201,7 +201,7 @@ class ES_Campaign_Report extends ES_List_Table {
201
  /**
202
  * Render a column when no column specific method exist.
203
  *
204
- * @param array $item
205
  * @param string $column_name
206
  *
207
  * @return mixed
@@ -215,7 +215,7 @@ class ES_Campaign_Report extends ES_List_Table {
215
  $status = ! empty( $item['status'] ) ? $item['status'] : ( ! empty( $item['es_deliver_sentstatus'] ) ? $item['es_deliver_sentstatus'] : '' );
216
 
217
  switch ( $status ) {
218
- case 'Sent':
219
  ?>
220
  <svg class="h-6 w-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
221
  <title><?php echo esc_html__( 'Sent', 'email-subscribers' ); ?></title>
@@ -223,7 +223,7 @@ class ES_Campaign_Report extends ES_List_Table {
223
  </svg>
224
  <?php
225
  break;
226
- case 'In Queue':
227
  ?>
228
  <svg class=" h-6 w-6 text-orange-400" fill="currentColor" viewBox="0 0 20 20">
229
  <title><?php echo esc_html__( 'In Queue', 'email-subscribers' ); ?></title>
@@ -231,7 +231,7 @@ class ES_Campaign_Report extends ES_List_Table {
231
  </svg>
232
  <?php
233
  break;
234
- case 'Sending':
235
  ?>
236
  <svg class=" h-6 w-6 text-yellow-400" fill="currentColor" viewBox="0 0 20 20">
237
  <title><?php echo esc_html__( 'Sending', 'email-subscribers' ); ?></title>
@@ -239,7 +239,7 @@ class ES_Campaign_Report extends ES_List_Table {
239
  </svg>
240
  <?php
241
  break;
242
- case 'Opened':
243
  ?>
244
  <svg xmlns="http://www.w3.org/2000/svg" class="" width="28" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" style="color:green">
245
  <title><?php echo esc_html__( 'Opened', 'email-subscribers' ); ?></title>
@@ -249,12 +249,12 @@ class ES_Campaign_Report extends ES_List_Table {
249
  </svg>
250
  <?php
251
  break;
252
- case '':
253
  ?>
254
  <i class="dashicons dashicons-es dashicons-minus"/>
255
  <?php
256
  break;
257
- default:
258
  echo esc_html( $status );
259
  break;
260
 
@@ -263,33 +263,31 @@ class ES_Campaign_Report extends ES_List_Table {
263
 
264
  /**
265
  * Get view activity table data
266
- *
267
  */
268
  public function get_activity_table_data( $return_count = false ) {
269
 
270
  global $wpbd;
271
 
272
- $hash = ig_es_get_request_data( 'list', '' );
273
- $campaign_id = ig_es_get_request_data( 'campaign_id', '' );
274
  $filter_by_status = ig_es_get_request_data( 'status', '' );
275
  $filter_by_country = ig_es_get_request_data( 'country_code', '' );
276
  $search = ig_es_get_request_data( 's' );
277
  $orderby = ig_es_get_request_data( 'orderby' );
278
- $order = ig_es_get_request_data( 'order', 'DESC' );
279
  $page_number = ig_es_get_request_data( 'paged', 1 );
280
-
281
- $message_id = 0;
282
  $view_activity_data = array();
283
  $delivery_table_exists = false;
284
  $selects = array();
285
 
286
-
287
- if ( ! empty( $hash ) ) {
288
  $notification_data_from_hash = ES_DB_Mailing_Queue::get_notification_by_hash( $hash );
289
- $campaign_id = $notification_data_from_hash['campaign_id'];
290
- $message_id = $notification_data_from_hash['id'];
291
  $delivery_table_exists = ES()->campaigns_db->table_exists( $wpbd->prefix . 'es_deliverreport' );
292
-
293
  // We are assigning NULL values to sent_at and opened_at columns as actions tables have NULL values for these columns when no data is present in the column.
294
  // Assigning NULL ensures sorting works as expected when both the tables are combined.
295
  $queue_query = "SELECT queue.contact_id AS `contact_id`, queue.email AS `email`, 0 AS `type`, NULL AS `sent_at`, NULL AS `opened_at`, queue.status, '' AS `country`, '' AS `device`, '' AS `email_client`, '' AS `os`
@@ -308,8 +306,8 @@ class ES_Campaign_Report extends ES_List_Table {
308
  '' AS `device`,
309
  '' AS `email_client`,
310
  '' AS `os`
311
- FROM {$wpbd->prefix}es_deliverreport WHERE es_deliver_sentguid = %s",
312
- array( $hash )
313
  );
314
 
315
  $selects[] = $wpbd->prepare( $queue_query, $message_id, $campaign_id, $message_id );
@@ -341,7 +339,7 @@ class ES_Campaign_Report extends ES_List_Table {
341
  IG_MESSAGE_SENT,
342
  IG_MESSAGE_OPEN,
343
  );
344
-
345
  $selects[] = $wpbd->prepare( $action_query, $query_args );
346
 
347
  if ( $return_count ) {
@@ -355,23 +353,23 @@ class ES_Campaign_Report extends ES_List_Table {
355
  $notification = ES()->campaigns_db->get( $campaign_id );
356
  $total_email_sent = ES()->actions_db->get_count_based_on_id_type( $notification['id'], $message_id, IG_MESSAGE_SENT );
357
  $email_viewed_count = ES()->actions_db->get_count_based_on_id_type( $notification['id'], $message_id, IG_MESSAGE_OPEN );
358
-
359
  $notification_query .= ' WHERE 1';
360
-
361
  $search_query = '';
362
  if ( ! empty( $search ) ) {
363
- $search_query = $wpbd->prepare( ' AND email LIKE %s', '%' . $wpbd->esc_like( $search ) . '%');
364
  }
365
 
366
  $status_query = '';
367
- if ( ! empty( $filter_by_status) ) {
368
  $status = 'not_opened' === $filter_by_status ? 'Sent' : 'Opened';
369
- $status_query = $wpbd->prepare( ' AND `status` = %s', $status );
370
  }
371
 
372
  $country_query = '';
373
  if ( ! empty( $filter_by_country ) ) {
374
- $country_query = $wpbd->prepare( ' AND `country` = %s', $filter_by_country );
375
  }
376
 
377
  $order_by_query = '';
@@ -390,15 +388,15 @@ class ES_Campaign_Report extends ES_List_Table {
390
 
391
  $order_by_query = " ORDER BY {$orderby} LIMIT {$offset}, {$per_page}";
392
  }
393
-
394
  $notification_query .= $search_query . $status_query . $country_query . $order_by_query;
395
  if ( $return_count ) {
396
  $count = $wpbd->get_var( $notification_query );
397
  if ( empty( $count ) && $delivery_table_exists ) {
398
  $count_query = 'SELECT count(*) FROM ( ' . $delivery_query . ' ) AS delivery_report WHERE 1';
399
  $count_query .= $search_query . $status_query . $country_query . $order_by_query;
400
-
401
- // If no results exists then check data into es_deliverreport table as earlier version were using this table.
402
  $count = $wpbd->get_var(
403
  $count_query
404
  );
@@ -420,26 +418,26 @@ class ES_Campaign_Report extends ES_List_Table {
420
  }
421
 
422
  $sr_no = $offset + 1;
423
- if ( ! empty( $results ) ) {
424
  $date_format = get_option( 'date_format' );
425
  $time_format = get_option( 'time_format' );
426
- $format = $date_format . ' ' . $time_format;
427
  foreach ( $results as $notification_action ) {
428
-
429
  $contact_id = $notification_action['contact_id'];
430
-
431
- $view_activity_data[$contact_id] = array(
432
- 'sr_no' => $sr_no++,
433
- 'email' => $notification_action['email'],
434
  'opened_at' => ! empty( $notification_action['opened_at'] ) ? ES_Common::convert_timestamp_to_date( $notification_action['opened_at'], $format ) : '',
435
- 'sent_at' => ! empty( $notification_action['sent_at'] ) ? ES_Common::convert_timestamp_to_date( $notification_action['sent_at'], $format ) : '',
436
- 'status' => $notification_action['status'],
437
  'country_flag' => '',
438
  'device' => '',
439
  'email_client' => '',
440
  'os' => '',
441
  );
442
-
443
  $view_activity_data = apply_filters( 'additional_es_report_activity_data', $view_activity_data, $contact_id, $notification_action );
444
  }
445
  }
@@ -448,7 +446,7 @@ class ES_Campaign_Report extends ES_List_Table {
448
  if ( ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
449
  $insight = ig_es_get_request_data( 'insight', '' );
450
  $_wpnonce = ig_es_get_request_data( '_wpnonce', '' );
451
-
452
  if ( ( ES()->is_pro() || $insight ) && 0 !== $message_id ) {
453
  do_action( 'ig_es_view_report_data', $hash );
454
  }
@@ -465,7 +463,7 @@ class ES_Campaign_Report extends ES_List_Table {
465
  </div>
466
  <?php
467
  }
468
-
469
  return $view_activity_data;
470
  }
471
 
@@ -473,8 +471,8 @@ class ES_Campaign_Report extends ES_List_Table {
473
  * Handling filtering and sorting for view activity table
474
  */
475
  public function es_view_activity_report_sort_and_filter() {
476
- $hash = ig_es_get_request_data( 'list', '' );
477
- $campaign_id = ig_es_get_request_data( 'campaign_id', '' );
478
 
479
  ?>
480
 
21
  );
22
 
23
  add_action( 'ig_es_view_activity_table_html', array( $this, 'view_activity_report_table' ), 10, 3 );
24
+ add_action( 'admin_footer', array( $this, 'es_view_activity_report_sort_and_filter' ) );
25
  }
26
 
27
  public function es_campaign_report_callback() {
29
 
30
  <?php
31
  $this->ajax_response();
32
+ $paged = ig_es_get_request_data( 'paged', 1 );
33
  $campaign_class = '';
34
 
35
  if ( ES()->is_pro() ) {
51
  </div>
52
  </div>
53
  </div>
54
+ <?php
55
  }
56
 
57
  public function ajax_response() {
74
  $headers = ob_get_clean();
75
 
76
  ob_start();
77
+ $this->pagination( 'top' );
78
  $pagination_top = ob_get_clean();
79
 
80
  ob_start();
81
+ $this->pagination( 'bottom' );
82
  $pagination_bottom = ob_get_clean();
83
 
84
  $response = array( 'rows' => $rows );
85
+
86
+ $response['column_headers'] = $headers;
87
+ $response['pagination']['top'] = $pagination_top;
88
  $response['pagination']['bottom'] = $pagination_bottom;
89
 
90
  if ( isset( $total_items ) ) {
93
  }
94
 
95
  if ( isset( $total_pages ) ) {
96
+ $response['total_pages'] = $total_pages;
97
  $response['total_pages_i18n'] = number_format_i18n( $total_pages );
98
  }
99
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
100
+ die( json_encode( $response ) );
101
+
102
  } else {
103
  return $response;
104
  }
112
  public function get_sortable_columns() {
113
 
114
  $sortable_columns = array(
115
+ 'email' => array( 'email', false ),
116
+ 'country_flag' => array( 'country_flag', false ),
117
+ 'os' => array( 'os', false ),
118
+ 'email_client' => array( 'email_client', false ),
119
+ 'sent_at' => array( 'sent_at', false ),
120
+ 'opened_at' => array( 'opened_at', false ),
121
+ 'status' => array( 'status', false ),
122
  );
123
 
124
  return $sortable_columns;
125
  }
126
+
127
 
128
  /**
129
  * Handles data query and filter, sorting, and pagination.
130
  */
131
  public function prepare_items() {
132
+
133
  $per_page = 100;
134
  $columns = $this->get_columns();
135
  $hidden = array();
136
  $sortable = $this->get_sortable_columns();
137
+
138
+ $this->_column_headers = array( $columns, $hidden, $sortable );
139
+
140
  $data = $this->get_activity_table_data();
141
  $total_items = $this->get_activity_table_data( true );
142
 
143
  $this->items = $data;
144
+
145
  /**
146
  * Call to _set_pagination_args method for informations about
147
  * total items, items for page, total pages and ordering
148
  */
149
  $this->set_pagination_args(
150
  array(
151
+ 'total_items' => $total_items,
152
+ 'per_page' => $per_page,
153
  )
154
  );
155
  }
156
 
157
  /**
158
+ * Method to handle display of WP_List table
159
  *
160
  * @Override of display method
161
  */
174
  * @since 4.6.12
175
  */
176
  public function search_box( $text = '', $input_id = '' ) {
177
+ do_action( 'ig_es_campaign_reports_filter_options', $text, $input_id );
178
  }
179
 
180
+
181
  /**
182
  * Associative array of columns
183
  *
185
  */
186
  public function get_columns() {
187
  $columns = array(
188
+ 'sr_no' => '#',
189
+ 'email' => __( 'Email', 'email-subscribers' ),
190
+ 'status' => __( 'Status', 'email-subscribers' ),
191
+ 'sent_at' => __( 'Sent Date', 'email-subscribers' ),
192
+ 'opened_at' => __( 'Viewed Date', 'email-subscribers' ),
193
+
194
  );
195
 
196
  $columns = apply_filters( 'additional_es_campaign_report_columns', $columns );
201
  /**
202
  * Render a column when no column specific method exist.
203
  *
204
+ * @param array $item
205
  * @param string $column_name
206
  *
207
  * @return mixed
215
  $status = ! empty( $item['status'] ) ? $item['status'] : ( ! empty( $item['es_deliver_sentstatus'] ) ? $item['es_deliver_sentstatus'] : '' );
216
 
217
  switch ( $status ) {
218
+ case 'Sent':
219
  ?>
220
  <svg class="h-6 w-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
221
  <title><?php echo esc_html__( 'Sent', 'email-subscribers' ); ?></title>
223
  </svg>
224
  <?php
225
  break;
226
+ case 'In Queue':
227
  ?>
228
  <svg class=" h-6 w-6 text-orange-400" fill="currentColor" viewBox="0 0 20 20">
229
  <title><?php echo esc_html__( 'In Queue', 'email-subscribers' ); ?></title>
231
  </svg>
232
  <?php
233
  break;
234
+ case 'Sending':
235
  ?>
236
  <svg class=" h-6 w-6 text-yellow-400" fill="currentColor" viewBox="0 0 20 20">
237
  <title><?php echo esc_html__( 'Sending', 'email-subscribers' ); ?></title>
239
  </svg>
240
  <?php
241
  break;
242
+ case 'Opened':
243
  ?>
244
  <svg xmlns="http://www.w3.org/2000/svg" class="" width="28" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" style="color:green">
245
  <title><?php echo esc_html__( 'Opened', 'email-subscribers' ); ?></title>
249
  </svg>
250
  <?php
251
  break;
252
+ case '':
253
  ?>
254
  <i class="dashicons dashicons-es dashicons-minus"/>
255
  <?php
256
  break;
257
+ default:
258
  echo esc_html( $status );
259
  break;
260
 
263
 
264
  /**
265
  * Get view activity table data
 
266
  */
267
  public function get_activity_table_data( $return_count = false ) {
268
 
269
  global $wpbd;
270
 
271
+ $hash = ig_es_get_request_data( 'list', '' );
272
+ $campaign_id = ig_es_get_request_data( 'campaign_id', '' );
273
  $filter_by_status = ig_es_get_request_data( 'status', '' );
274
  $filter_by_country = ig_es_get_request_data( 'country_code', '' );
275
  $search = ig_es_get_request_data( 's' );
276
  $orderby = ig_es_get_request_data( 'orderby' );
277
+ $order = ig_es_get_request_data( 'order', 'DESC' );
278
  $page_number = ig_es_get_request_data( 'paged', 1 );
279
+
280
+ $message_id = 0;
281
  $view_activity_data = array();
282
  $delivery_table_exists = false;
283
  $selects = array();
284
 
285
+ if ( ! empty( $hash ) ) {
 
286
  $notification_data_from_hash = ES_DB_Mailing_Queue::get_notification_by_hash( $hash );
287
+ $campaign_id = $notification_data_from_hash['campaign_id'];
288
+ $message_id = $notification_data_from_hash['id'];
289
  $delivery_table_exists = ES()->campaigns_db->table_exists( $wpbd->prefix . 'es_deliverreport' );
290
+
291
  // We are assigning NULL values to sent_at and opened_at columns as actions tables have NULL values for these columns when no data is present in the column.
292
  // Assigning NULL ensures sorting works as expected when both the tables are combined.
293
  $queue_query = "SELECT queue.contact_id AS `contact_id`, queue.email AS `email`, 0 AS `type`, NULL AS `sent_at`, NULL AS `opened_at`, queue.status, '' AS `country`, '' AS `device`, '' AS `email_client`, '' AS `os`
306
  '' AS `device`,
307
  '' AS `email_client`,
308
  '' AS `os`
309
+ FROM {$wpbd->prefix}es_deliverreport WHERE es_deliver_sentguid = %s",
310
+ array( $hash )
311
  );
312
 
313
  $selects[] = $wpbd->prepare( $queue_query, $message_id, $campaign_id, $message_id );
339
  IG_MESSAGE_SENT,
340
  IG_MESSAGE_OPEN,
341
  );
342
+
343
  $selects[] = $wpbd->prepare( $action_query, $query_args );
344
 
345
  if ( $return_count ) {
353
  $notification = ES()->campaigns_db->get( $campaign_id );
354
  $total_email_sent = ES()->actions_db->get_count_based_on_id_type( $notification['id'], $message_id, IG_MESSAGE_SENT );
355
  $email_viewed_count = ES()->actions_db->get_count_based_on_id_type( $notification['id'], $message_id, IG_MESSAGE_OPEN );
356
+
357
  $notification_query .= ' WHERE 1';
358
+
359
  $search_query = '';
360
  if ( ! empty( $search ) ) {
361
+ $search_query = $wpbd->prepare( ' AND email LIKE %s', '%' . $wpbd->esc_like( $search ) . '%' );
362
  }
363
 
364
  $status_query = '';
365
+ if ( ! empty( $filter_by_status ) ) {
366
  $status = 'not_opened' === $filter_by_status ? 'Sent' : 'Opened';
367
+ $status_query = $wpbd->prepare( ' AND `status` = %s', $status );
368
  }
369
 
370
  $country_query = '';
371
  if ( ! empty( $filter_by_country ) ) {
372
+ $country_query = $wpbd->prepare( ' AND `country` = %s', $filter_by_country );
373
  }
374
 
375
  $order_by_query = '';
388
 
389
  $order_by_query = " ORDER BY {$orderby} LIMIT {$offset}, {$per_page}";
390
  }
391
+
392
  $notification_query .= $search_query . $status_query . $country_query . $order_by_query;
393
  if ( $return_count ) {
394
  $count = $wpbd->get_var( $notification_query );
395
  if ( empty( $count ) && $delivery_table_exists ) {
396
  $count_query = 'SELECT count(*) FROM ( ' . $delivery_query . ' ) AS delivery_report WHERE 1';
397
  $count_query .= $search_query . $status_query . $country_query . $order_by_query;
398
+
399
+ // If no results exists then check data into es_deliverreport table as earlier version were using this table.
400
  $count = $wpbd->get_var(
401
  $count_query
402
  );
418
  }
419
 
420
  $sr_no = $offset + 1;
421
+ if ( ! empty( $results ) ) {
422
  $date_format = get_option( 'date_format' );
423
  $time_format = get_option( 'time_format' );
424
+ $format = $date_format . ' ' . $time_format;
425
  foreach ( $results as $notification_action ) {
426
+
427
  $contact_id = $notification_action['contact_id'];
428
+
429
+ $view_activity_data[ $contact_id ] = array(
430
+ 'sr_no' => $sr_no++,
431
+ 'email' => $notification_action['email'],
432
  'opened_at' => ! empty( $notification_action['opened_at'] ) ? ES_Common::convert_timestamp_to_date( $notification_action['opened_at'], $format ) : '',
433
+ 'sent_at' => ! empty( $notification_action['sent_at'] ) ? ES_Common::convert_timestamp_to_date( $notification_action['sent_at'], $format ) : '',
434
+ 'status' => $notification_action['status'],
435
  'country_flag' => '',
436
  'device' => '',
437
  'email_client' => '',
438
  'os' => '',
439
  );
440
+
441
  $view_activity_data = apply_filters( 'additional_es_report_activity_data', $view_activity_data, $contact_id, $notification_action );
442
  }
443
  }
446
  if ( ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
447
  $insight = ig_es_get_request_data( 'insight', '' );
448
  $_wpnonce = ig_es_get_request_data( '_wpnonce', '' );
449
+
450
  if ( ( ES()->is_pro() || $insight ) && 0 !== $message_id ) {
451
  do_action( 'ig_es_view_report_data', $hash );
452
  }
463
  </div>
464
  <?php
465
  }
466
+
467
  return $view_activity_data;
468
  }
469
 
471
  * Handling filtering and sorting for view activity table
472
  */
473
  public function es_view_activity_report_sort_and_filter() {
474
+ $hash = ig_es_get_request_data( 'list', '' );
475
+ $campaign_id = ig_es_get_request_data( 'campaign_id', '' );
476
 
477
  ?>
478
 
lite/includes/classes/class-es-campaigns-table.php CHANGED
@@ -57,7 +57,7 @@ class ES_Campaigns_Table extends ES_List_Table {
57
 
58
  /**
59
  * Get class instance.
60
- *
61
  * @since 4.7.8
62
  */
63
  public static function get_instance() {
@@ -115,7 +115,7 @@ class ES_Campaigns_Table extends ES_List_Table {
115
  global $ig_es_tracker;
116
  ?>
117
  <div class="wrap pt-4 font-sans">
118
- <?php
119
  if ( 'broadcast_created' === $action ) {
120
 
121
  // Trigger feedback popup for broadcast creation.
@@ -136,7 +136,7 @@ class ES_Campaigns_Table extends ES_List_Table {
136
  <!-- End-IG-Code -->
137
  <a href="admin.php?page=es_newsletters" class="ig-es-title-button ml-2 align-middle"><?php esc_html_e( 'Send Broadcast', 'email-subscribers' ); ?></a>
138
 
139
- <?php
140
  do_action( 'ig_es_after_campaign_type_buttons' );
141
 
142
  // Start-IG-Code.
@@ -218,8 +218,8 @@ class ES_Campaigns_Table extends ES_List_Table {
218
  $sql = 'SELECT * FROM ' . IG_CAMPAIGNS_TABLE;
219
  }
220
 
221
- $args = array();
222
- $query = array();
223
  $add_where_clause = true;
224
 
225
  $query[] = "( deleted_at IS NULL OR deleted_at = '0000-00-00 00:00:00' )";
@@ -346,7 +346,7 @@ class ES_Campaigns_Table extends ES_List_Table {
346
 
347
  return ES_Common::prepare_list_name_by_ids( $list_ids );
348
  } else {
349
- $type = isset( $item['type'] ) ? $item['type'] : '';
350
  $list_ids = array();
351
  if ( 'newsletter' === $type && ! empty( $item['meta'] ) ) {
352
  $list_ids = ES()->campaigns_db->get_list_ids( $item );
@@ -372,7 +372,7 @@ class ES_Campaigns_Table extends ES_List_Table {
372
  $categories = ES_Common::convert_categories_string_to_array( $item[ $column_name ], false );
373
  if ( strpos( $item[ $column_name ], '{a}All{a}' ) ) {
374
  $categories = __( 'All', 'email-subscribers' );
375
- } else if ( strpos( $item[ $column_name ], '{a}None{a}' ) ) {
376
  $categories = __( 'None', 'email-subscribers' );
377
  } else {
378
  $categories = trim( trim( implode( ', ', $categories ) ), ',' );
@@ -478,8 +478,6 @@ class ES_Campaigns_Table extends ES_List_Table {
478
 
479
  $actions['report'] = '<a href="?page=' . esc_attr( 'es_reports' ) . '&action=view&list=' . $report['hash'] . '&_wpnonce=" ' . $es_nonce . '" class="text-indigo-600">' . esc_html__( 'Report', 'email-subscribers' ) . '</a>';
480
  }
481
-
482
-
483
  }
484
 
485
  $campaign_type = array( 'post_notification', 'post_digest' );
@@ -519,9 +517,11 @@ class ES_Campaigns_Table extends ES_List_Table {
519
  <label for="<?php echo esc_attr( 'ig-es-campaign-status-toggle-' . $campaign_id ); ?>" class="ig-es-campaign-status-toggle-label inline-flex items-center cursor-pointer">
520
  <span class="relative">
521
  <input id="<?php echo esc_attr( 'ig-es-campaign-status-toggle-' . $campaign_id ); ?>" type="checkbox" class="absolute es-check-toggle opacity-0 w-0 h-0" name="<?php echo esc_attr( 'ig-es-campaign-status-toggle-' . $campaign_id ); ?>" value="<?php echo esc_attr( $campaign_id ); ?>"
522
- <?php
523
- checked( IG_ES_CAMPAIGN_STATUS_ACTIVE,
524
- $campaign_status );
 
 
525
  ?>
526
  >
527
  <span class="es-mail-toggle-line"></span>
@@ -674,7 +674,7 @@ class ES_Campaigns_Table extends ES_List_Table {
674
  * @since 4.0.0
675
  * @since 4.3.4 Added esc_attr()
676
  */
677
- public function search_box( $text = '', $input_id = '' ) {
678
  ?>
679
  <p class="search-box">
680
  <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_attr( $text ); ?>:</label>
@@ -684,24 +684,24 @@ class ES_Campaigns_Table extends ES_List_Table {
684
  <p class="search-box search-group-box box-ma10">
685
  <?php $filter_by_status = ig_es_get_request_data( 'filter_by_campaign_status' ); ?>
686
  <select name="filter_by_campaign_status" id="ig_es_filter_campaign_status_by_type">
687
- <?php
688
- $allowedtags = ig_es_allowed_html_tags_in_esc();
689
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
690
- $campaign_types = ES_Common::prepare_campaign_statuses_dropdown_options( $filter_by_status, __( 'All Statuses', 'email-subscribers' ) );
691
- echo wp_kses( $campaign_types , $allowedtags );
692
  ?>
693
  </select>
694
  </p>
695
  <p class="search-box search-group-box box-ma10">
696
  <?php $filter_by_campaign_type = ig_es_get_request_data( 'filter_by_campaign_type' ); ?>
697
  <select name="filter_by_campaign_type" id="ig_es_filter_campaign_type">
698
- <?php
699
  $campaign_statuses = ES_Common::prepare_campaign_type_dropdown_options( $filter_by_campaign_type, __( 'All Type', 'email-subscribers' ) );
700
- echo wp_kses( $campaign_statuses , $allowedtags );
701
  ?>
702
  </select>
703
  </p>
704
- <?php
705
  }
706
 
707
  /**
57
 
58
  /**
59
  * Get class instance.
60
+ *
61
  * @since 4.7.8
62
  */
63
  public static function get_instance() {
115
  global $ig_es_tracker;
116
  ?>
117
  <div class="wrap pt-4 font-sans">
118
+ <?php
119
  if ( 'broadcast_created' === $action ) {
120
 
121
  // Trigger feedback popup for broadcast creation.
136
  <!-- End-IG-Code -->
137
  <a href="admin.php?page=es_newsletters" class="ig-es-title-button ml-2 align-middle"><?php esc_html_e( 'Send Broadcast', 'email-subscribers' ); ?></a>
138
 
139
+ <?php
140
  do_action( 'ig_es_after_campaign_type_buttons' );
141
 
142
  // Start-IG-Code.
218
  $sql = 'SELECT * FROM ' . IG_CAMPAIGNS_TABLE;
219
  }
220
 
221
+ $args = array();
222
+ $query = array();
223
  $add_where_clause = true;
224
 
225
  $query[] = "( deleted_at IS NULL OR deleted_at = '0000-00-00 00:00:00' )";
346
 
347
  return ES_Common::prepare_list_name_by_ids( $list_ids );
348
  } else {
349
+ $type = isset( $item['type'] ) ? $item['type'] : '';
350
  $list_ids = array();
351
  if ( 'newsletter' === $type && ! empty( $item['meta'] ) ) {
352
  $list_ids = ES()->campaigns_db->get_list_ids( $item );
372
  $categories = ES_Common::convert_categories_string_to_array( $item[ $column_name ], false );
373
  if ( strpos( $item[ $column_name ], '{a}All{a}' ) ) {
374
  $categories = __( 'All', 'email-subscribers' );
375
+ } elseif ( strpos( $item[ $column_name ], '{a}None{a}' ) ) {
376
  $categories = __( 'None', 'email-subscribers' );
377
  } else {
378
  $categories = trim( trim( implode( ', ', $categories ) ), ',' );
478
 
479
  $actions['report'] = '<a href="?page=' . esc_attr( 'es_reports' ) . '&action=view&list=' . $report['hash'] . '&_wpnonce=" ' . $es_nonce . '" class="text-indigo-600">' . esc_html__( 'Report', 'email-subscribers' ) . '</a>';
480
  }
 
 
481
  }
482
 
483
  $campaign_type = array( 'post_notification', 'post_digest' );
517
  <label for="<?php echo esc_attr( 'ig-es-campaign-status-toggle-' . $campaign_id ); ?>" class="ig-es-campaign-status-toggle-label inline-flex items-center cursor-pointer">
518
  <span class="relative">
519
  <input id="<?php echo esc_attr( 'ig-es-campaign-status-toggle-' . $campaign_id ); ?>" type="checkbox" class="absolute es-check-toggle opacity-0 w-0 h-0" name="<?php echo esc_attr( 'ig-es-campaign-status-toggle-' . $campaign_id ); ?>" value="<?php echo esc_attr( $campaign_id ); ?>"
520
+ <?php
521
+ checked(
522
+ IG_ES_CAMPAIGN_STATUS_ACTIVE,
523
+ $campaign_status
524
+ );
525
  ?>
526
  >
527
  <span class="es-mail-toggle-line"></span>
674
  * @since 4.0.0
675
  * @since 4.3.4 Added esc_attr()
676
  */
677
+ public function search_box( $text = '', $input_id = '' ) {
678
  ?>
679
  <p class="search-box">
680
  <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_attr( $text ); ?>:</label>
684
  <p class="search-box search-group-box box-ma10">
685
  <?php $filter_by_status = ig_es_get_request_data( 'filter_by_campaign_status' ); ?>
686
  <select name="filter_by_campaign_status" id="ig_es_filter_campaign_status_by_type">
687
+ <?php
688
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
689
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
690
+ $campaign_types = ES_Common::prepare_campaign_statuses_dropdown_options( $filter_by_status, __( 'All Statuses', 'email-subscribers' ) );
691
+ echo wp_kses( $campaign_types, $allowedtags );
692
  ?>
693
  </select>
694
  </p>
695
  <p class="search-box search-group-box box-ma10">
696
  <?php $filter_by_campaign_type = ig_es_get_request_data( 'filter_by_campaign_type' ); ?>
697
  <select name="filter_by_campaign_type" id="ig_es_filter_campaign_type">
698
+ <?php
699
  $campaign_statuses = ES_Common::prepare_campaign_type_dropdown_options( $filter_by_campaign_type, __( 'All Type', 'email-subscribers' ) );
700
+ echo wp_kses( $campaign_statuses, $allowedtags );
701
  ?>
702
  </select>
703
  </p>
704
+ <?php
705
  }
706
 
707
  /**
lite/includes/classes/class-es-contacts-table.php CHANGED
@@ -15,7 +15,6 @@ class ES_Contacts_Table extends ES_List_Table {
15
  *
16
  * @since 4.0.0
17
  * @var array
18
- *
19
  */
20
  public $contact_lists_statuses = array();
21
 
@@ -25,7 +24,6 @@ class ES_Contacts_Table extends ES_List_Table {
25
  * @since 4.2.1
26
  *
27
  * @var string
28
- *
29
  */
30
  public static $option_per_page = 'es_contacts_per_page';
31
 
@@ -34,7 +32,6 @@ class ES_Contacts_Table extends ES_List_Table {
34
  *
35
  * @since 4.0.0
36
  * @var array
37
- *
38
  */
39
  public $list_ids = array();
40
 
@@ -43,7 +40,6 @@ class ES_Contacts_Table extends ES_List_Table {
43
  *
44
  * @since 4.0.0
45
  * @var array
46
- *
47
  */
48
  public $lists_id_name_map = array();
49
 
@@ -52,7 +48,6 @@ class ES_Contacts_Table extends ES_List_Table {
52
  *
53
  * @since 4.6.5
54
  * @var array
55
- *
56
  */
57
  public $items_data = array();
58
 
@@ -116,7 +111,7 @@ class ES_Contacts_Table extends ES_List_Table {
116
  * Get the content of Audience main tab
117
  *
118
  * @param $active_tab
119
- * @param array $audience_main_tabs
120
  *
121
  * @return array
122
  *
@@ -125,7 +120,7 @@ class ES_Contacts_Table extends ES_List_Table {
125
  public function get_audience_main_tabs( $active_tab, $audience_main_tabs = array() ) {
126
 
127
  $audience_tab_main_navigation = array(
128
- 'new_contact' => array(
129
  'label' => __( 'Add New Contact', 'email-subscribers' ),
130
  'indicator_option' => '',
131
  'indicator_label' => '',
@@ -134,7 +129,7 @@ class ES_Contacts_Table extends ES_List_Table {
134
  'url' => add_query_arg( 'action', 'new', 'admin.php?page=es_subscribers' ),
135
  ),
136
 
137
- 'import' => array(
138
  'label' => __( 'Import Contacts', 'email-subscribers' ),
139
  'indicator_option' => '',
140
  'indicator_label' => '',
@@ -483,14 +478,14 @@ class ES_Contacts_Table extends ES_List_Table {
483
  if ( ! $is_error ) {
484
 
485
  $lists = ! empty( $lists ) ? $lists : array( 1 => 0 );
486
-
487
  $existing_subscribed_lists = ES()->lists_contacts_db->get_list_ids_by_contact( $id, 'subscribed' );
488
  ES()->lists_contacts_db->update_contact_lists( $id, $lists );
489
  $updated_subscribed_lists = ES()->lists_contacts_db->get_list_ids_by_contact( $id, 'subscribed' );
490
 
491
  // Lists whose status changed to unconfirmed or unsubscribed from subscribed.
492
  $changed_lists = array_diff( $existing_subscribed_lists, $updated_subscribed_lists );
493
-
494
  // Check if admin has updated status of any subscribed lists.
495
  if ( ! $is_new && ! empty( $changed_lists ) ) {
496
  do_action( 'ig_es_admin_contact_unsubscribe', $id, 0, 0, $changed_lists );
@@ -507,13 +502,13 @@ class ES_Contacts_Table extends ES_List_Table {
507
  $name = ES_Common::prepare_name_from_first_name_last_name( $contact['first_name'], $contact['last_name'] );
508
 
509
  $template_data = array(
510
- 'email' => $contact['email'],
511
  'contact_id' => $id,
512
- 'name' => $name,
513
  'first_name' => $contact['first_name'],
514
- 'last_name' => $contact['last_name'],
515
- 'guid' => $contact['hash'],
516
- 'list_name' => $list_name,
517
  );
518
 
519
  // Send Welcome Email.
@@ -648,7 +643,7 @@ class ES_Contacts_Table extends ES_List_Table {
648
  }
649
 
650
  $filter_sql .= $list_filter_sql;
651
- $query[] = "id IN ( $filter_sql )";
652
  }
653
 
654
  // Prepare search query
@@ -693,7 +688,7 @@ class ES_Contacts_Table extends ES_List_Table {
693
  $sql .= $order_by_clause;
694
  $sql .= " LIMIT {$offset}, {$per_page}";
695
 
696
- $cache_key = ES_Cache::generate_key( $sql );
697
  $exists_in_cache = ES_Cache::is_exists( $cache_key, 'query' );
698
 
699
  if ( ! $exists_in_cache ) {
@@ -703,8 +698,8 @@ class ES_Contacts_Table extends ES_List_Table {
703
  $result = ES_Cache::get( $cache_key, 'query' );
704
  }
705
  } else {
706
-
707
- $cache_key = ES_Cache::generate_key( $sql );
708
  $exists_in_cache = ES_Cache::is_exists( $cache_key, 'query' );
709
  if ( ! $exists_in_cache ) {
710
  $result = $wpbd->get_var( $sql );
@@ -884,7 +879,7 @@ class ES_Contacts_Table extends ES_List_Table {
884
  /**
885
  * Render a column when no column specific method exist.
886
  *
887
- * @param array $item
888
  * @param string $column_name
889
  *
890
  * @return mixed
@@ -938,7 +933,7 @@ class ES_Contacts_Table extends ES_List_Table {
938
 
939
  $selected = ! empty( $list_contact_status_map[ $list_id ] ) ? $list_contact_status_map[ $list_id ] : '';
940
 
941
- $status_dropdown_html = '<select class="h-8 form-select w-40 mt-2 mr-8 shadow-sm border-gray-400 ig-es-statuses-dropdown shadow-sm sm:text-sm sm:leading-5" name="contact_data[lists][' . esc_attr( $list_id ) . ']" >';
942
  $status_dropdown_html .= ES_Common::prepare_statuses_dropdown_options( $selected );
943
  $status_dropdown_html .= '</select>';
944
 
@@ -947,7 +942,7 @@ class ES_Contacts_Table extends ES_List_Table {
947
  $status_span = '<span class="border-gray-400 focus:bg-gray-100 es_list_contact_status ' . $list_contact_status_map[ $list_id ] . '" title="' . ucwords( $list_contact_status_map[ $list_id ] ) . '">';
948
  }
949
 
950
- $list_name = strlen( $list_name ) > 15 ? substr( $list_name, 0, 15 ) . '...' : $list_name;
951
  $lists_html .= "<td class='pr-1 pt-2 text-sm leading-5 font-normal text-gray-500'>$status_span$list_name</td><td>$status_dropdown_html</td>";
952
 
953
  $i ++;
@@ -1023,8 +1018,8 @@ class ES_Contacts_Table extends ES_List_Table {
1023
  $contact_id = $item['id'];
1024
  $name = ES_Common::prepare_name_from_first_name_last_name( $item['first_name'], $item['last_name'] );
1025
 
1026
- $title = '<strong class="pl-1">' . $name . '</strong>';
1027
- $page = ig_es_get_request_data( 'page' );
1028
 
1029
  $actions = array(
1030
  'edit' => '<a href="?page=' . esc_attr( $page ) . '&action=edit&subscriber=' . absint( $item['id'] ) . '&_wpnonce=' . $delete_nonce . '" class="text-indigo-600">' . esc_html__( 'Edit', 'email-subscribers' ) . '</a>',
@@ -1034,9 +1029,9 @@ class ES_Contacts_Table extends ES_List_Table {
1034
 
1035
  if ( isset( $this->contact_lists_statuses[ $contact_id ] ) ) {
1036
  $lists_statuses = $this->contact_lists_statuses[ $contact_id ];
1037
-
1038
  if ( ! empty( $lists_statuses ) ) {
1039
-
1040
  $has_unconfirmed_status = false;
1041
  foreach ( $lists_statuses as $list_status ) {
1042
  if ( 'unconfirmed' === $list_status ) {
@@ -1044,7 +1039,7 @@ class ES_Contacts_Table extends ES_List_Table {
1044
  break;
1045
  }
1046
  }
1047
-
1048
  // Show resend confirmation email option only when contact has unconfirmed status in atleast one list.
1049
  if ( $has_unconfirmed_status ) {
1050
  $actions['resend'] = '<a href="?page=' . esc_attr( $page ) . '&action=resend&subscriber=' . absint( $item['id'] ) . '&_wpnonce=' . $delete_nonce . '" class="text-indigo-600">' . esc_html__( 'Resend Confirmation', 'email-subscribers' ) . '</a>';
@@ -1063,14 +1058,14 @@ class ES_Contacts_Table extends ES_List_Table {
1063
  * @since 4.0.0
1064
  */
1065
  public function get_columns() {
1066
- $columns = array(
1067
- 'cb' => '<input type="checkbox"/>',
1068
- 'name' => __( 'Name', 'email-subscribers' ),
1069
- 'email' => __( 'Email', 'email-subscribers' ),
1070
- 'lists' => __( 'List(s)', 'email-subscribers' ),
1071
- 'created_at' => __( 'Created', 'email-subscribers' )
1072
  );
1073
-
1074
  return $columns;
1075
  }
1076
 
@@ -1101,10 +1096,10 @@ class ES_Contacts_Table extends ES_List_Table {
1101
  */
1102
  public function get_bulk_actions() {
1103
  $actions = array(
1104
- 'bulk_delete' => __( 'Delete', 'email-subscribers' ),
1105
- 'bulk_list_update' => __( 'Move to list', 'email-subscribers' ),
1106
- 'bulk_list_add' => __( 'Add to list', 'email-subscribers' ),
1107
- 'bulk_status_update' => __( 'Change status', 'email-subscribers' ),
1108
  );
1109
 
1110
  $bulk_actions = apply_filters( 'ig_es_contacts_bulk_action', $actions );
@@ -1215,7 +1210,7 @@ class ES_Contacts_Table extends ES_List_Table {
1215
  * @since 4.0.0
1216
  */
1217
  public function prepare_lists_dropdown() {
1218
- $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">';
1219
  $data .= ES_Common::prepare_list_dropdown_options();
1220
  $data .= '</select>';
1221
 
@@ -1229,7 +1224,7 @@ class ES_Contacts_Table extends ES_List_Table {
1229
  * @since 4.0.0
1230
  */
1231
  public function prepare_statuses_dropdown() {
1232
- $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;">';
1233
  $data .= ES_Common::prepare_statuses_dropdown_options();
1234
  $data .= '</select>';
1235
 
15
  *
16
  * @since 4.0.0
17
  * @var array
 
18
  */
19
  public $contact_lists_statuses = array();
20
 
24
  * @since 4.2.1
25
  *
26
  * @var string
 
27
  */
28
  public static $option_per_page = 'es_contacts_per_page';
29
 
32
  *
33
  * @since 4.0.0
34
  * @var array
 
35
  */
36
  public $list_ids = array();
37
 
40
  *
41
  * @since 4.0.0
42
  * @var array
 
43
  */
44
  public $lists_id_name_map = array();
45
 
48
  *
49
  * @since 4.6.5
50
  * @var array
 
51
  */
52
  public $items_data = array();
53
 
111
  * Get the content of Audience main tab
112
  *
113
  * @param $active_tab
114
+ * @param array $audience_main_tabs
115
  *
116
  * @return array
117
  *
120
  public function get_audience_main_tabs( $active_tab, $audience_main_tabs = array() ) {
121
 
122
  $audience_tab_main_navigation = array(
123
+ 'new_contact' => array(
124
  'label' => __( 'Add New Contact', 'email-subscribers' ),
125
  'indicator_option' => '',
126
  'indicator_label' => '',
129
  'url' => add_query_arg( 'action', 'new', 'admin.php?page=es_subscribers' ),
130
  ),
131
 
132
+ 'import' => array(
133
  'label' => __( 'Import Contacts', 'email-subscribers' ),
134
  'indicator_option' => '',
135
  'indicator_label' => '',
478
  if ( ! $is_error ) {
479
 
480
  $lists = ! empty( $lists ) ? $lists : array( 1 => 0 );
481
+
482
  $existing_subscribed_lists = ES()->lists_contacts_db->get_list_ids_by_contact( $id, 'subscribed' );
483
  ES()->lists_contacts_db->update_contact_lists( $id, $lists );
484
  $updated_subscribed_lists = ES()->lists_contacts_db->get_list_ids_by_contact( $id, 'subscribed' );
485
 
486
  // Lists whose status changed to unconfirmed or unsubscribed from subscribed.
487
  $changed_lists = array_diff( $existing_subscribed_lists, $updated_subscribed_lists );
488
+
489
  // Check if admin has updated status of any subscribed lists.
490
  if ( ! $is_new && ! empty( $changed_lists ) ) {
491
  do_action( 'ig_es_admin_contact_unsubscribe', $id, 0, 0, $changed_lists );
502
  $name = ES_Common::prepare_name_from_first_name_last_name( $contact['first_name'], $contact['last_name'] );
503
 
504
  $template_data = array(
505
+ 'email' => $contact['email'],
506
  'contact_id' => $id,
507
+ 'name' => $name,
508
  'first_name' => $contact['first_name'],
509
+ 'last_name' => $contact['last_name'],
510
+ 'guid' => $contact['hash'],
511
+ 'list_name' => $list_name,
512
  );
513
 
514
  // Send Welcome Email.
643
  }
644
 
645
  $filter_sql .= $list_filter_sql;
646
+ $query[] = "id IN ( $filter_sql )";
647
  }
648
 
649
  // Prepare search query
688
  $sql .= $order_by_clause;
689
  $sql .= " LIMIT {$offset}, {$per_page}";
690
 
691
+ $cache_key = ES_Cache::generate_key( $sql );
692
  $exists_in_cache = ES_Cache::is_exists( $cache_key, 'query' );
693
 
694
  if ( ! $exists_in_cache ) {
698
  $result = ES_Cache::get( $cache_key, 'query' );
699
  }
700
  } else {
701
+
702
+ $cache_key = ES_Cache::generate_key( $sql );
703
  $exists_in_cache = ES_Cache::is_exists( $cache_key, 'query' );
704
  if ( ! $exists_in_cache ) {
705
  $result = $wpbd->get_var( $sql );
879
  /**
880
  * Render a column when no column specific method exist.
881
  *
882
+ * @param array $item
883
  * @param string $column_name
884
  *
885
  * @return mixed
933
 
934
  $selected = ! empty( $list_contact_status_map[ $list_id ] ) ? $list_contact_status_map[ $list_id ] : '';
935
 
936
+ $status_dropdown_html = '<select class="h-8 form-select w-40 mt-2 mr-8 shadow-sm border-gray-400 ig-es-statuses-dropdown shadow-sm sm:text-sm sm:leading-5" name="contact_data[lists][' . esc_attr( $list_id ) . ']" >';
937
  $status_dropdown_html .= ES_Common::prepare_statuses_dropdown_options( $selected );
938
  $status_dropdown_html .= '</select>';
939
 
942
  $status_span = '<span class="border-gray-400 focus:bg-gray-100 es_list_contact_status ' . $list_contact_status_map[ $list_id ] . '" title="' . ucwords( $list_contact_status_map[ $list_id ] ) . '">';
943
  }
944
 
945
+ $list_name = strlen( $list_name ) > 15 ? substr( $list_name, 0, 15 ) . '...' : $list_name;
946
  $lists_html .= "<td class='pr-1 pt-2 text-sm leading-5 font-normal text-gray-500'>$status_span$list_name</td><td>$status_dropdown_html</td>";
947
 
948
  $i ++;
1018
  $contact_id = $item['id'];
1019
  $name = ES_Common::prepare_name_from_first_name_last_name( $item['first_name'], $item['last_name'] );
1020
 
1021
+ $title = '<strong class="pl-1">' . $name . '</strong>';
1022
+ $page = ig_es_get_request_data( 'page' );
1023
 
1024
  $actions = array(
1025
  'edit' => '<a href="?page=' . esc_attr( $page ) . '&action=edit&subscriber=' . absint( $item['id'] ) . '&_wpnonce=' . $delete_nonce . '" class="text-indigo-600">' . esc_html__( 'Edit', 'email-subscribers' ) . '</a>',
1029
 
1030
  if ( isset( $this->contact_lists_statuses[ $contact_id ] ) ) {
1031
  $lists_statuses = $this->contact_lists_statuses[ $contact_id ];
1032
+
1033
  if ( ! empty( $lists_statuses ) ) {
1034
+
1035
  $has_unconfirmed_status = false;
1036
  foreach ( $lists_statuses as $list_status ) {
1037
  if ( 'unconfirmed' === $list_status ) {
1039
  break;
1040
  }
1041
  }
1042
+
1043
  // Show resend confirmation email option only when contact has unconfirmed status in atleast one list.
1044
  if ( $has_unconfirmed_status ) {
1045
  $actions['resend'] = '<a href="?page=' . esc_attr( $page ) . '&action=resend&subscriber=' . absint( $item['id'] ) . '&_wpnonce=' . $delete_nonce . '" class="text-indigo-600">' . esc_html__( 'Resend Confirmation', 'email-subscribers' ) . '</a>';
1058
  * @since 4.0.0
1059
  */
1060
  public function get_columns() {
1061
+ $columns = array(
1062
+ 'cb' => '<input type="checkbox"/>',
1063
+ 'name' => __( 'Name', 'email-subscribers' ),
1064
+ 'email' => __( 'Email', 'email-subscribers' ),
1065
+ 'lists' => __( 'List(s)', 'email-subscribers' ),
1066
+ 'created_at' => __( 'Created', 'email-subscribers' ),
1067
  );
1068
+
1069
  return $columns;
1070
  }
1071
 
1096
  */
1097
  public function get_bulk_actions() {
1098
  $actions = array(
1099
+ 'bulk_delete' => __( 'Delete', 'email-subscribers' ),
1100
+ 'bulk_list_update' => __( 'Move to list', 'email-subscribers' ),
1101
+ 'bulk_list_add' => __( 'Add to list', 'email-subscribers' ),
1102
+ 'bulk_status_update' => __( 'Change status', 'email-subscribers' ),
1103
  );
1104
 
1105
  $bulk_actions = apply_filters( 'ig_es_contacts_bulk_action', $actions );
1210
  * @since 4.0.0
1211
  */
1212
  public function prepare_lists_dropdown() {
1213
+ $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">';
1214
  $data .= ES_Common::prepare_list_dropdown_options();
1215
  $data .= '</select>';
1216
 
1224
  * @since 4.0.0
1225
  */
1226
  public function prepare_statuses_dropdown() {
1227
+ $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;">';
1228
  $data .= ES_Common::prepare_statuses_dropdown_options();
1229
  $data .= '</select>';
1230
 
lite/includes/classes/class-es-cron.php CHANGED
@@ -133,14 +133,14 @@ class ES_Cron {
133
 
134
  $is_woocommerce_active = $ig_es_tracker::is_plugin_activated( 'woocommerce/woocommerce.php' );
135
  if ( $is_woocommerce_active ) {
136
-
137
  if ( IG_ES_Abandoned_Cart_Options::is_cart_tracking_enabled() ) {
138
-
139
  if ( ! wp_next_scheduled( 'ig_es_wc_abandoned_cart_worker' ) ) {
140
  wp_schedule_event( floor( time() / 300 ) * 300, 'ig_es_two_minutes', 'ig_es_wc_abandoned_cart_worker' );
141
  }
142
  }
143
-
144
  // Cron job to detect WooCommerce products which are on sale.
145
  if ( ! wp_next_scheduled( 'ig_es_wc_products_on_sale_worker' ) ) {
146
  wp_schedule_event( floor( time() / 300 ) * 300, 'ig_es_fifteen_minutes', 'ig_es_wc_products_on_sale_worker' );
@@ -148,7 +148,6 @@ class ES_Cron {
148
  }
149
  }
150
 
151
-
152
  }
153
 
154
  /**
@@ -258,11 +257,11 @@ class ES_Cron {
258
  public function cron_schedules( $schedules = array() ) {
259
 
260
  $es_schedules = array(
261
- 'ig_es_cron_interval' => array(
262
  'interval' => $this->get_cron_interval(),
263
  'display' => __( 'Email Subscribers Cronjob Interval', 'email-subscribers' ),
264
  ),
265
- 'ig_es_two_minutes' => array(
266
  'interval' => 2 * MINUTE_IN_SECONDS,
267
  'display' => __( 'Two minutes', 'email-subscribers' ),
268
  ),
@@ -316,8 +315,8 @@ class ES_Cron {
316
  /**
317
  * Get Cron URL
318
  *
319
- * @param bool $self
320
- * @param bool $pro
321
  * @param string $campaign_hash
322
  *
323
  * @return mixed|string|void
@@ -563,7 +562,6 @@ class ES_Cron {
563
  * Handle Data Request
564
  *
565
  * @since 4.6.6
566
- *
567
  */
568
  public function handle_data_request() {
569
  $es_request = ig_es_get_request_data( 'es' );
@@ -664,9 +662,9 @@ class ES_Cron {
664
 
665
  /**
666
  * Get cron guid
667
- *
668
  * @return string $guid
669
- *
670
  * @since 4.7.7
671
  */
672
  public function get_cron_guid() {
133
 
134
  $is_woocommerce_active = $ig_es_tracker::is_plugin_activated( 'woocommerce/woocommerce.php' );
135
  if ( $is_woocommerce_active ) {
136
+
137
  if ( IG_ES_Abandoned_Cart_Options::is_cart_tracking_enabled() ) {
138
+
139
  if ( ! wp_next_scheduled( 'ig_es_wc_abandoned_cart_worker' ) ) {
140
  wp_schedule_event( floor( time() / 300 ) * 300, 'ig_es_two_minutes', 'ig_es_wc_abandoned_cart_worker' );
141
  }
142
  }
143
+
144
  // Cron job to detect WooCommerce products which are on sale.
145
  if ( ! wp_next_scheduled( 'ig_es_wc_products_on_sale_worker' ) ) {
146
  wp_schedule_event( floor( time() / 300 ) * 300, 'ig_es_fifteen_minutes', 'ig_es_wc_products_on_sale_worker' );
148
  }
149
  }
150
 
 
151
  }
152
 
153
  /**
257
  public function cron_schedules( $schedules = array() ) {
258
 
259
  $es_schedules = array(
260
+ 'ig_es_cron_interval' => array(
261
  'interval' => $this->get_cron_interval(),
262
  'display' => __( 'Email Subscribers Cronjob Interval', 'email-subscribers' ),
263
  ),
264
+ 'ig_es_two_minutes' => array(
265
  'interval' => 2 * MINUTE_IN_SECONDS,
266
  'display' => __( 'Two minutes', 'email-subscribers' ),
267
  ),
315
  /**
316
  * Get Cron URL
317
  *
318
+ * @param bool $self
319
+ * @param bool $pro
320
  * @param string $campaign_hash
321
  *
322
  * @return mixed|string|void
562
  * Handle Data Request
563
  *
564
  * @since 4.6.6
 
565
  */
566
  public function handle_data_request() {
567
  $es_request = ig_es_get_request_data( 'es' );
662
 
663
  /**
664
  * Get cron guid
665
+ *
666
  * @return string $guid
667
+ *
668
  * @since 4.7.7
669
  */
670
  public function get_cron_guid() {
lite/includes/classes/class-es-export-subscribers.php CHANGED
@@ -111,16 +111,16 @@ class Export_Subscribers {
111
  }*/
112
 
113
  $export_nonce = wp_create_nonce( 'ig-es-subscriber-export-nonce' );
114
- $url = "admin.php?page=download_report&report=users&status={$key}&export-nonce={$export_nonce}";
115
 
116
  ?>
117
 
118
  <tr class="border-b text-sm font-normal text-gray-700 border-gray-200" id="ig_es_export_<?php echo esc_attr( $key ); ?>">
119
  <td class="py-2 pl-10 w-1/12"><?php echo esc_html( $i ); ?></td>
120
  <td class="py-2 pl-4 w-2/12">
121
- <?php
122
  $allowedtags = ig_es_allowed_html_tags_in_esc();
123
- echo wp_kses( $export_list , $allowedtags );
124
  ?>
125
  </td>
126
  <td class="py-2 pl-8 w-2/12 font-medium ig_es_total_contacts"><?php echo esc_html( $this->count_subscribers( $key ) ); ?></td>
@@ -186,12 +186,12 @@ class Export_Subscribers {
186
  </table>
187
  </form>
188
  </div>
189
- <?php
190
  }
191
 
192
 
193
  /**
194
- * Count total subscribers
195
  *
196
  * @param string $status
197
  *
@@ -281,12 +281,12 @@ class Export_Subscribers {
281
 
282
  // Add filter to increase memory limit
283
  add_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' );
284
-
285
  wp_raise_memory_limit( 'ig_es' );
286
 
287
  // Remove the added filter function so that it won't be called again if wp_raise_memory_limit called later on.
288
  remove_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' );
289
-
290
  set_time_limit( IG_SET_TIME_LIMIT );
291
 
292
  $results = array();
111
  }*/
112
 
113
  $export_nonce = wp_create_nonce( 'ig-es-subscriber-export-nonce' );
114
+ $url = "admin.php?page=download_report&report=users&status={$key}&export-nonce={$export_nonce}";
115
 
116
  ?>
117
 
118
  <tr class="border-b text-sm font-normal text-gray-700 border-gray-200" id="ig_es_export_<?php echo esc_attr( $key ); ?>">
119
  <td class="py-2 pl-10 w-1/12"><?php echo esc_html( $i ); ?></td>
120
  <td class="py-2 pl-4 w-2/12">
121
+ <?php
122
  $allowedtags = ig_es_allowed_html_tags_in_esc();
123
+ echo wp_kses( $export_list, $allowedtags );
124
  ?>
125
  </td>
126
  <td class="py-2 pl-8 w-2/12 font-medium ig_es_total_contacts"><?php echo esc_html( $this->count_subscribers( $key ) ); ?></td>
186
  </table>
187
  </form>
188
  </div>
189
+ <?php
190
  }
191
 
192
 
193
  /**
194
+ * Count total subscribers
195
  *
196
  * @param string $status
197
  *
281
 
282
  // Add filter to increase memory limit
283
  add_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' );
284
+
285
  wp_raise_memory_limit( 'ig_es' );
286
 
287
  // Remove the added filter function so that it won't be called again if wp_raise_memory_limit called later on.
288
  remove_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' );
289
+
290
  set_time_limit( IG_SET_TIME_LIMIT );
291
 
292
  $results = array();
lite/includes/classes/class-es-form-widget.php CHANGED
@@ -17,10 +17,10 @@ class ES_Form_Widget extends WP_Widget {
17
 
18
  $title = apply_filters( 'widget_title', $title );
19
 
20
- echo wp_kses_post( $args['before_widget'] );
21
 
22
  if ( ! empty( $title ) ) {
23
- echo wp_kses_post( sprintf( '%s %s %s', $args['before_title'] , $title , $args['after_title']) );
24
  }
25
 
26
  $form_id = isset( $instance['form_id'] ) ? esc_attr( $instance['form_id'] ) : 0;
@@ -69,10 +69,10 @@ class ES_Form_Widget extends WP_Widget {
69
  <p>
70
  <label for="widget-email-subscribers-2-es_group"><?php esc_html_e( 'Forms', 'email-subscribers' ); ?></label>
71
  <select id="<?php echo esc_attr( $this->get_field_id( 'form_id' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'form_id' ) ); ?>" class="widefat" style="width:100%;">
72
- <?php
73
- $form_dropdown = ES_Common::prepare_form_dropdown_options( $selected_form_id, null );
74
- $allowedtags = ig_es_allowed_html_tags_in_esc();
75
- echo wp_kses( $form_dropdown , $allowedtags );
76
  ?>
77
  </select>
78
  </p>
17
 
18
  $title = apply_filters( 'widget_title', $title );
19
 
20
+ echo wp_kses_post( $args['before_widget'] );
21
 
22
  if ( ! empty( $title ) ) {
23
+ echo wp_kses_post( sprintf( '%s %s %s', $args['before_title'], $title, $args['after_title'] ) );
24
  }
25
 
26
  $form_id = isset( $instance['form_id'] ) ? esc_attr( $instance['form_id'] ) : 0;
69
  <p>
70
  <label for="widget-email-subscribers-2-es_group"><?php esc_html_e( 'Forms', 'email-subscribers' ); ?></label>
71
  <select id="<?php echo esc_attr( $this->get_field_id( 'form_id' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'form_id' ) ); ?>" class="widefat" style="width:100%;">
72
+ <?php
73
+ $form_dropdown = ES_Common::prepare_form_dropdown_options( $selected_form_id, null );
74
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
75
+ echo wp_kses( $form_dropdown, $allowedtags );
76
  ?>
77
  </select>
78
  </p>
lite/includes/classes/class-es-forms-table.php CHANGED
@@ -79,13 +79,13 @@ class ES_Forms_Table extends ES_List_Table {
79
  $action = ig_es_get_request_data( 'action' );
80
  ?>
81
  <div class="wrap pt-4 font-sans">
82
- <?php
83
  if ( 'new' === $action ) {
84
  $this->es_new_form_callback();
85
  } elseif ( 'edit' === $action ) {
86
  $form = ig_es_get_request_data( 'form' );
87
  echo wp_kses_post( $this->edit_form( absint( $form ) ) );
88
- } else {
89
  ?>
90
  <div class="flex">
91
  <div>
@@ -95,12 +95,12 @@ class ES_Forms_Table extends ES_List_Table {
95
  </div>
96
  <div class="mt-1">
97
  <a href="admin.php?page=es_forms&action=new" class="ig-es-title-button ml-2 leading-5 align-middle">
98
- <?php esc_html_e('Add New', 'email-subscribers'); ?>
99
  </a>
100
  </div>
101
  </div>
102
  <div><hr class="wp-header-end"></div>
103
- <?php
104
  if ( 'form_created' === $action ) {
105
  $message = __( 'Form added successfully!', 'email-subscribers' );
106
  ES_Common::show_message( $message, 'success' );
@@ -133,7 +133,7 @@ class ES_Forms_Table extends ES_List_Table {
133
  <br class="clear">
134
  </div>
135
  </div>
136
- <?php
137
  }
138
  }
139
 
@@ -308,7 +308,7 @@ class ES_Forms_Table extends ES_List_Table {
308
  <div class="w-1/2">
309
  <ol class="list-none p-0 inline-flex">
310
  <li class="flex items-center text-sm tracking-wide">
311
- <a class="hover:underline" href="admin.php?page=es_forms"><?php esc_html_e('Forms ', 'email-subscribers'); ?></a>
312
  <svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
313
  </li>
314
  </ol>
@@ -331,7 +331,7 @@ class ES_Forms_Table extends ES_List_Table {
331
  <div class="w-1/2 -mt-2.5 inline text-right">
332
  <a class="px-1.5 py-2 mt-2 es-documentation" href="https://www.icegram.com/documentation/how-to-create-a-form-in-email-subscribers/?utm_source=in_app&utm_medium=es_forms&utm_campaign=es_doc" target="_blank">
333
  <svg class="w-6 h-6 -mt-1 inline text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
334
- <title><?php esc_html_e('Documentation ', 'email-subscribers'); ?></title>
335
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
336
  </svg>
337
  </a>
@@ -411,34 +411,34 @@ class ES_Forms_Table extends ES_List_Table {
411
 
412
  <td class="pr-6 pb-8">
413
  <input type="checkbox" class="form-checkbox es_visible" name="form_data[name_visible]" value="yes"
414
- <?php
415
  if ( 'yes' === $form_data['name_visible'] ) {
416
  echo 'checked="checked"';
417
- }
418
  ?>
419
  />
420
  </td>
421
  <td class="pr-6 pb-8">
422
  <input type="checkbox" class="form-checkbox es_required" name="form_data[name_required]" value="yes"
423
- <?php
424
  if ( 'yes' === $form_data['name_required'] ) {
425
  echo 'checked="checked"';
426
- }
427
  ?>
428
  />
429
  </td>
430
  <td class="pr-6 pb-8"><input class="es_name_label form-input block border-gray-400 w-5/6 pr-12 h-8 shadow-sm focus:bg-gray-100 sm:text-sm sm:leading-5" name="form_data[name_label]" value="<?php echo esc_attr( $form_data['name_label'] ); ?>"
431
- <?php
432
  if ( 'yes' === $form_data['name_required'] ) {
433
  echo 'disabled=disabled';
434
- }
435
  ?>
436
  ></td>
437
  <td class="pr-6 pb-8"><input class="es_name_label form-input block border-gray-400 w-5/6 pr-12 h-8 shadow-sm focus:bg-gray-100 sm:text-sm sm:leading-5" name="form_data[name_place_holder]" value="<?php echo esc_attr( $form_data['name_place_holder'] ); ?>"
438
- <?php
439
  if ( 'yes' === $form_data['name_required'] ) {
440
  echo 'disabled=disabled';
441
- }
442
  ?>
443
  ></td>
444
  </tr>
@@ -466,15 +466,15 @@ class ES_Forms_Table extends ES_List_Table {
466
  $allowedtags = ig_es_allowed_html_tags_in_esc();
467
  if ( count( $lists ) > 0 ) {
468
  $lists_checkboxes = ES_Shortcode::prepare_lists_checkboxes( $lists, array_keys( $lists ), 3, (array) $form_data['lists'] );
469
- echo wp_kses( $lists_checkboxes , $allowedtags );
470
 
471
  } else {
472
  $create_list_link = admin_url( 'admin.php?page=es_lists&action=new' );
473
  ?>
474
  <span><b class="text-sm font-normal text-gray-600 pb-2">
475
- <?php
476
  /* translators: %s: Create list page url */
477
- echo sprintf( esc_html__('List not found. Please %s', 'email-subscribers' ), '<a href="' . esc_url( $create_list_link ) . '"> ' . esc_html__( 'create your first list', 'email-subscribers') . '</a>' );
478
  ?>
479
  </b></span>
480
  <?php } ?>
@@ -494,7 +494,7 @@ class ES_Forms_Table extends ES_List_Table {
494
  <label for="allow_contact" class=" inline-flex items-center cursor-pointer">
495
  <span class="relative">
496
  <input id="allow_contact" type="checkbox" class=" absolute es-check-toggle opacity-0 w-0 h-0" name="form_data[list_visible]" value="yes"
497
- <?php
498
  if ( 'yes' === $form_data['list_visible'] ) {
499
  echo 'checked="checked"';
500
  }
@@ -513,7 +513,7 @@ class ES_Forms_Table extends ES_List_Table {
513
  </div>
514
 
515
 
516
- <?php do_action('ig_es_add_additional_options', $form_data); ?>
517
 
518
 
519
  <div class="flex flex-row border-b border-gray-100">
@@ -531,7 +531,7 @@ class ES_Forms_Table extends ES_List_Table {
531
  <label for="gdpr_consent" class=" inline-flex items-center cursor-pointer">
532
  <span class="relative">
533
  <input id="gdpr_consent" type="checkbox" class="absolute es-check-toggle opacity-0 w-0 h-0" name="form_data[gdpr_consent]" value="yes"
534
- <?php
535
  if ( 'yes' === $form_data['gdpr_consent'] ) {
536
  echo 'checked="checked"';
537
  }
@@ -558,11 +558,11 @@ class ES_Forms_Table extends ES_List_Table {
558
  <input type="hidden" name="submitted" value="submitted"/>
559
  <?php
560
  $submit_button_text = $is_new ? __( 'Save Form', 'email-subscribers' ) : __( 'Save Changes', 'email-subscribers' );
561
- if ( count( $lists ) > 0 ) {
562
  ?>
563
  <p class="submit"><input type="submit" name="submit" id="ig_es_campaign_post_notification_submit_button" class="cursor-pointer align-middle ig-es-primary-button px-4 py-2 ml-6 mr-2" value="<?php echo esc_attr( $submit_button_text ); ?>"/>
564
  <a href="admin.php?page=es_forms" class="cursor-pointer align-middle rounded-md border border-indigo-600 hover:shadow-md focus:outline-none focus:shadow-outline-indigo text-sm leading-5 font-medium transition ease-in-out duration-150 px-4 my-2 py-2 mx-2 "><?php esc_html_e( 'Cancel', 'email-subscribers' ); ?></a></p>
565
- <?php
566
  } else {
567
  $lists_page_url = admin_url( 'admin.php?page=es_lists' );
568
  /* translators: %s: List Page url */
@@ -619,62 +619,62 @@ class ES_Forms_Table extends ES_List_Table {
619
  $af_id = ! empty( $data['af_id'] ) ? $data['af_id'] : 0;
620
  $gdpr_consent = ! empty( $data['gdpr_consent'] ) ? sanitize_text_field( $data['gdpr_consent'] ) : 'no';
621
  $gdpr_consent_text = ! empty( $data['gdpr_consent_text'] ) ? wp_kses_post( $data['gdpr_consent_text'] ) : '';
622
- $captcha = ! empty( $data['captcha'] ) ? ES_Common::get_captcha_setting(null, $data) : 'no';
623
 
624
  $body = array(
625
  array(
626
- 'type' => 'text',
627
- 'name' => 'Name',
628
- 'id' => 'name',
629
- 'params' => array(
630
  'label' => $name_label,
631
  'place_holder' => $name_place_holder,
632
  'show' => $name_visible,
633
- 'required' => $name_required
634
  ),
635
 
636
- 'position' => 1
637
  ),
638
 
639
  array(
640
- 'type' => 'text',
641
- 'name' => 'Email',
642
- 'id' => 'email',
643
- 'params' => array(
644
  'label' => $email_label,
645
  'place_holder' => $email_place_holder,
646
  'show' => true,
647
- 'required' => true
648
  ),
649
 
650
- 'position' => 2
651
  ),
652
 
653
  array(
654
- 'type' => 'checkbox',
655
- 'name' => 'Lists',
656
- 'id' => 'lists',
657
- 'params' => array(
658
  'label' => 'Lists',
659
  'show' => $list_visible,
660
  'required' => $list_required,
661
- 'values' => $list_ids
662
  ),
663
 
664
- 'position' => 3
665
  ),
666
 
667
  array(
668
- 'type' => 'submit',
669
- 'name' => 'submit',
670
- 'id' => 'submit',
671
- 'params' => array(
672
  'label' => $button_label,
673
  'show' => true,
674
- 'required' => true
675
  ),
676
 
677
- 'position' => 4
678
  ),
679
 
680
  );
@@ -683,11 +683,11 @@ class ES_Forms_Table extends ES_List_Table {
683
  'lists' => $list_ids,
684
  'desc' => $desc,
685
  'form_version' => ES()->forms_db->version,
686
- 'captcha' => $captcha,
687
  'gdpr' => array(
688
  'consent' => $gdpr_consent,
689
- 'consent_text' => $gdpr_consent_text
690
- )
691
 
692
  );
693
 
@@ -717,14 +717,23 @@ class ES_Forms_Table extends ES_List_Table {
717
  $gdpr_consent = 'no';
718
  $gdpr_consent_text = '';
719
 
720
- $captcha = ES_Common::get_captcha_setting( $id , $settings_data);
721
 
722
  if ( ! empty( $settings_data['gdpr'] ) ) {
723
  $gdpr_consent = ! empty( $settings_data['gdpr']['consent'] ) ? $settings_data['gdpr']['consent'] : 'no';
724
  $gdpr_consent_text = ! empty( $settings_data['gdpr']['consent_text'] ) ? $settings_data['gdpr']['consent_text'] : '';
725
  }
726
 
727
- $form_data = array( 'form_id' => $id, 'name' => $name, 'af_id' => $af_id, 'desc' => $desc, 'form_version' => $form_version, 'gdpr_consent' => $gdpr_consent, 'gdpr_consent_text' => $gdpr_consent_text, 'captcha' => $captcha );
 
 
 
 
 
 
 
 
 
728
 
729
  foreach ( $body_data as $d ) {
730
  if ( 'name' === $d['id'] ) {
@@ -769,7 +778,7 @@ class ES_Forms_Table extends ES_List_Table {
769
  $sql = "SELECT * FROM {$forms_table}";
770
  }
771
 
772
- $args = array();
773
  $query = array();
774
 
775
  $add_where_clause = false;
@@ -896,11 +905,11 @@ class ES_Forms_Table extends ES_List_Table {
896
  */
897
  public function get_columns() {
898
  $columns = array(
899
- 'cb' => '<input type="checkbox" />',
900
- 'name' => __( 'Name', 'email-subscribers' ),
901
- 'shortcode' => __( 'Shortcode', 'email-subscribers' ),
902
- 'total_active_subscribers' => __( 'Subscribers', 'email-subscribers' ),
903
- 'created_at' => __( 'Created', 'email-subscribers' ),
904
  );
905
 
906
  return $columns;
@@ -987,7 +996,7 @@ class ES_Forms_Table extends ES_List_Table {
987
  return $statuses[ $status ];
988
  }
989
 
990
- public function search_box( $text, $input_id) {
991
  ?>
992
 
993
  <p class="search-box">
79
  $action = ig_es_get_request_data( 'action' );
80
  ?>
81
  <div class="wrap pt-4 font-sans">
82
+ <?php
83
  if ( 'new' === $action ) {
84
  $this->es_new_form_callback();
85
  } elseif ( 'edit' === $action ) {
86
  $form = ig_es_get_request_data( 'form' );
87
  echo wp_kses_post( $this->edit_form( absint( $form ) ) );
88
+ } else {
89
  ?>
90
  <div class="flex">
91
  <div>
95
  </div>
96
  <div class="mt-1">
97
  <a href="admin.php?page=es_forms&action=new" class="ig-es-title-button ml-2 leading-5 align-middle">
98
+ <?php esc_html_e( 'Add New', 'email-subscribers' ); ?>
99
  </a>
100
  </div>
101
  </div>
102
  <div><hr class="wp-header-end"></div>
103
+ <?php
104
  if ( 'form_created' === $action ) {
105
  $message = __( 'Form added successfully!', 'email-subscribers' );
106
  ES_Common::show_message( $message, 'success' );
133
  <br class="clear">
134
  </div>
135
  </div>
136
+ <?php
137
  }
138
  }
139
 
308
  <div class="w-1/2">
309
  <ol class="list-none p-0 inline-flex">
310
  <li class="flex items-center text-sm tracking-wide">
311
+ <a class="hover:underline" href="admin.php?page=es_forms"><?php esc_html_e( 'Forms ', 'email-subscribers' ); ?></a>
312
  <svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
313
  </li>
314
  </ol>
331
  <div class="w-1/2 -mt-2.5 inline text-right">
332
  <a class="px-1.5 py-2 mt-2 es-documentation" href="https://www.icegram.com/documentation/how-to-create-a-form-in-email-subscribers/?utm_source=in_app&utm_medium=es_forms&utm_campaign=es_doc" target="_blank">
333
  <svg class="w-6 h-6 -mt-1 inline text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
334
+ <title><?php esc_html_e( 'Documentation ', 'email-subscribers' ); ?></title>
335
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
336
  </svg>
337
  </a>
411
 
412
  <td class="pr-6 pb-8">
413
  <input type="checkbox" class="form-checkbox es_visible" name="form_data[name_visible]" value="yes"
414
+ <?php
415
  if ( 'yes' === $form_data['name_visible'] ) {
416
  echo 'checked="checked"';
417
+ }
418
  ?>
419
  />
420
  </td>
421
  <td class="pr-6 pb-8">
422
  <input type="checkbox" class="form-checkbox es_required" name="form_data[name_required]" value="yes"
423
+ <?php
424
  if ( 'yes' === $form_data['name_required'] ) {
425
  echo 'checked="checked"';
426
+ }
427
  ?>
428
  />
429
  </td>
430
  <td class="pr-6 pb-8"><input class="es_name_label form-input block border-gray-400 w-5/6 pr-12 h-8 shadow-sm focus:bg-gray-100 sm:text-sm sm:leading-5" name="form_data[name_label]" value="<?php echo esc_attr( $form_data['name_label'] ); ?>"
431
+ <?php
432
  if ( 'yes' === $form_data['name_required'] ) {
433
  echo 'disabled=disabled';
434
+ }
435
  ?>
436
  ></td>
437
  <td class="pr-6 pb-8"><input class="es_name_label form-input block border-gray-400 w-5/6 pr-12 h-8 shadow-sm focus:bg-gray-100 sm:text-sm sm:leading-5" name="form_data[name_place_holder]" value="<?php echo esc_attr( $form_data['name_place_holder'] ); ?>"
438
+ <?php
439
  if ( 'yes' === $form_data['name_required'] ) {
440
  echo 'disabled=disabled';
441
+ }
442
  ?>
443
  ></td>
444
  </tr>
466
  $allowedtags = ig_es_allowed_html_tags_in_esc();
467
  if ( count( $lists ) > 0 ) {
468
  $lists_checkboxes = ES_Shortcode::prepare_lists_checkboxes( $lists, array_keys( $lists ), 3, (array) $form_data['lists'] );
469
+ echo wp_kses( $lists_checkboxes, $allowedtags );
470
 
471
  } else {
472
  $create_list_link = admin_url( 'admin.php?page=es_lists&action=new' );
473
  ?>
474
  <span><b class="text-sm font-normal text-gray-600 pb-2">
475
+ <?php
476
  /* translators: %s: Create list page url */
477
+ echo sprintf( esc_html__( 'List not found. Please %s', 'email-subscribers' ), '<a href="' . esc_url( $create_list_link ) . '"> ' . esc_html__( 'create your first list', 'email-subscribers' ) . '</a>' );
478
  ?>
479
  </b></span>
480
  <?php } ?>
494
  <label for="allow_contact" class=" inline-flex items-center cursor-pointer">
495
  <span class="relative">
496
  <input id="allow_contact" type="checkbox" class=" absolute es-check-toggle opacity-0 w-0 h-0" name="form_data[list_visible]" value="yes"
497
+ <?php
498
  if ( 'yes' === $form_data['list_visible'] ) {
499
  echo 'checked="checked"';
500
  }
513
  </div>
514
 
515
 
516
+ <?php do_action( 'ig_es_add_additional_options', $form_data ); ?>
517
 
518
 
519
  <div class="flex flex-row border-b border-gray-100">
531
  <label for="gdpr_consent" class=" inline-flex items-center cursor-pointer">
532
  <span class="relative">
533
  <input id="gdpr_consent" type="checkbox" class="absolute es-check-toggle opacity-0 w-0 h-0" name="form_data[gdpr_consent]" value="yes"
534
+ <?php
535
  if ( 'yes' === $form_data['gdpr_consent'] ) {
536
  echo 'checked="checked"';
537
  }
558
  <input type="hidden" name="submitted" value="submitted"/>
559
  <?php
560
  $submit_button_text = $is_new ? __( 'Save Form', 'email-subscribers' ) : __( 'Save Changes', 'email-subscribers' );
561
+ if ( count( $lists ) > 0 ) {
562
  ?>
563
  <p class="submit"><input type="submit" name="submit" id="ig_es_campaign_post_notification_submit_button" class="cursor-pointer align-middle ig-es-primary-button px-4 py-2 ml-6 mr-2" value="<?php echo esc_attr( $submit_button_text ); ?>"/>
564
  <a href="admin.php?page=es_forms" class="cursor-pointer align-middle rounded-md border border-indigo-600 hover:shadow-md focus:outline-none focus:shadow-outline-indigo text-sm leading-5 font-medium transition ease-in-out duration-150 px-4 my-2 py-2 mx-2 "><?php esc_html_e( 'Cancel', 'email-subscribers' ); ?></a></p>
565
+ <?php
566
  } else {
567
  $lists_page_url = admin_url( 'admin.php?page=es_lists' );
568
  /* translators: %s: List Page url */
619
  $af_id = ! empty( $data['af_id'] ) ? $data['af_id'] : 0;
620
  $gdpr_consent = ! empty( $data['gdpr_consent'] ) ? sanitize_text_field( $data['gdpr_consent'] ) : 'no';
621
  $gdpr_consent_text = ! empty( $data['gdpr_consent_text'] ) ? wp_kses_post( $data['gdpr_consent_text'] ) : '';
622
+ $captcha = ! empty( $data['captcha'] ) ? ES_Common::get_captcha_setting( null, $data ) : 'no';
623
 
624
  $body = array(
625
  array(
626
+ 'type' => 'text',
627
+ 'name' => 'Name',
628
+ 'id' => 'name',
629
+ 'params' => array(
630
  'label' => $name_label,
631
  'place_holder' => $name_place_holder,
632
  'show' => $name_visible,
633
+ 'required' => $name_required,
634
  ),
635
 
636
+ 'position' => 1,
637
  ),
638
 
639
  array(
640
+ 'type' => 'text',
641
+ 'name' => 'Email',
642
+ 'id' => 'email',
643
+ 'params' => array(
644
  'label' => $email_label,
645
  'place_holder' => $email_place_holder,
646
  'show' => true,
647
+ 'required' => true,
648
  ),
649
 
650
+ 'position' => 2,
651
  ),
652
 
653
  array(
654
+ 'type' => 'checkbox',
655
+ 'name' => 'Lists',
656
+ 'id' => 'lists',
657
+ 'params' => array(
658
  'label' => 'Lists',
659
  'show' => $list_visible,
660
  'required' => $list_required,
661
+ 'values' => $list_ids,
662
  ),
663
 
664
+ 'position' => 3,
665
  ),
666
 
667
  array(
668
+ 'type' => 'submit',
669
+ 'name' => 'submit',
670
+ 'id' => 'submit',
671
+ 'params' => array(
672
  'label' => $button_label,
673
  'show' => true,
674
+ 'required' => true,
675
  ),
676
 
677
+ 'position' => 4,
678
  ),
679
 
680
  );
683
  'lists' => $list_ids,
684
  'desc' => $desc,
685
  'form_version' => ES()->forms_db->version,
686
+ 'captcha' => $captcha,
687
  'gdpr' => array(
688
  'consent' => $gdpr_consent,
689
+ 'consent_text' => $gdpr_consent_text,
690
+ ),
691
 
692
  );
693
 
717
  $gdpr_consent = 'no';
718
  $gdpr_consent_text = '';
719
 
720
+ $captcha = ES_Common::get_captcha_setting( $id, $settings_data );
721
 
722
  if ( ! empty( $settings_data['gdpr'] ) ) {
723
  $gdpr_consent = ! empty( $settings_data['gdpr']['consent'] ) ? $settings_data['gdpr']['consent'] : 'no';
724
  $gdpr_consent_text = ! empty( $settings_data['gdpr']['consent_text'] ) ? $settings_data['gdpr']['consent_text'] : '';
725
  }
726
 
727
+ $form_data = array(
728
+ 'form_id' => $id,
729
+ 'name' => $name,
730
+ 'af_id' => $af_id,
731
+ 'desc' => $desc,
732
+ 'form_version' => $form_version,
733
+ 'gdpr_consent' => $gdpr_consent,
734
+ 'gdpr_consent_text' => $gdpr_consent_text,
735
+ 'captcha' => $captcha,
736
+ );
737
 
738
  foreach ( $body_data as $d ) {
739
  if ( 'name' === $d['id'] ) {
778
  $sql = "SELECT * FROM {$forms_table}";
779
  }
780
 
781
+ $args = array();
782
  $query = array();
783
 
784
  $add_where_clause = false;
905
  */
906
  public function get_columns() {
907
  $columns = array(
908
+ 'cb' => '<input type="checkbox" />',
909
+ 'name' => __( 'Name', 'email-subscribers' ),
910
+ 'shortcode' => __( 'Shortcode', 'email-subscribers' ),
911
+ 'total_active_subscribers' => __( 'Subscribers', 'email-subscribers' ),
912
+ 'created_at' => __( 'Created', 'email-subscribers' ),
913
  );
914
 
915
  return $columns;
996
  return $statuses[ $status ];
997
  }
998
 
999
+ public function search_box( $text, $input_id ) {
1000
  ?>
1001
 
1002
  <p class="search-box">
lite/includes/classes/class-es-geolocation.php CHANGED
@@ -25,15 +25,15 @@ class ES_Geolocation {
25
  * @var array
26
  */
27
  private static $geoip_apis = array(
28
- 'ipinfo.io' => 'https://ipinfo.io/%s/json',
29
- 'ip-api.com' => 'http://ip-api.com/json/%s',
30
  );
31
 
32
  /**
33
  * Icegram API endpoints for geolocating an IP address
34
  *
35
  * @var string
36
- *
37
  * @since 4.7.3
38
  */
39
  private static $icegram_api_url = 'http://api.icegram.com/geo/';
@@ -131,10 +131,10 @@ class ES_Geolocation {
131
 
132
  // Use Icegram geo location API incase if we still don't have the location data.
133
  if ( empty( $geo_ip_data ) ) {
134
- $response = wp_safe_remote_get(
135
  self::$icegram_api_url . $ip_address,
136
- array(
137
- 'timeout' => 2
138
  )
139
  );
140
  if ( ! is_wp_error( $response ) && $response['body'] ) {
@@ -160,7 +160,7 @@ class ES_Geolocation {
160
  * @since 4.5.0
161
  */
162
  public static function get_countries_iso_code_name_map( $country_code = '' ) {
163
-
164
  $countries_data = self::get_countries();
165
 
166
  if ( isset( $countries_data[ $country_code ] ) ) {
25
  * @var array
26
  */
27
  private static $geoip_apis = array(
28
+ 'ipinfo.io' => 'https://ipinfo.io/%s/json',
29
+ 'ip-api.com' => 'http://ip-api.com/json/%s',
30
  );
31
 
32
  /**
33
  * Icegram API endpoints for geolocating an IP address
34
  *
35
  * @var string
36
+ *
37
  * @since 4.7.3
38
  */
39
  private static $icegram_api_url = 'http://api.icegram.com/geo/';
131
 
132
  // Use Icegram geo location API incase if we still don't have the location data.
133
  if ( empty( $geo_ip_data ) ) {
134
+ $response = wp_safe_remote_get(
135
  self::$icegram_api_url . $ip_address,
136
+ array(
137
+ 'timeout' => 2,
138
  )
139
  );
140
  if ( ! is_wp_error( $response ) && $response['body'] ) {
160
  * @since 4.5.0
161
  */
162
  public static function get_countries_iso_code_name_map( $country_code = '' ) {
163
+
164
  $countries_data = self::get_countries();
165
 
166
  if ( isset( $countries_data[ $country_code ] ) ) {
lite/includes/classes/class-es-handle-post-notification.php CHANGED
@@ -129,7 +129,7 @@ class ES_Handle_Post_Notification {
129
 
130
  // Add entry into mailing queue table
131
  $mailing_queue_id = ES_DB_Mailing_Queue::add_notification( $data );
132
-
133
  if ( $mailing_queue_id ) {
134
  $mailing_queue_hash = $guid;
135
  $campaign_id = $notification['id'];
@@ -161,13 +161,13 @@ class ES_Handle_Post_Notification {
161
  }
162
 
163
  public static function prepare_body( $es_templ_body, $post_id, $email_template_id ) {
164
- $post = get_post( $post_id );
165
- $post_key = 'post';
166
  // Making $post as global using $GLOBALS['post'] key. Can't use 'post' key directly into $GLOBALS since PHPCS throws global variable assignment warning for 'post'.
167
  $GLOBALS[ $post_key ] = $post;
168
 
169
- $post_date = ES_Common::convert_date_to_wp_date( $post->post_modified );
170
- $es_templ_body = str_replace( '{{DATE}}', $post_date, $es_templ_body );
171
 
172
  $post_title = get_the_title( $post );
173
  $es_templ_body = str_replace( '{{POSTTITLE}}', $post_title, $es_templ_body );
@@ -215,7 +215,7 @@ class ES_Handle_Post_Notification {
215
  $es_templ_body = str_replace( '{{POSTEXCERPT}}', $post_excerpt, $es_templ_body );
216
 
217
  $more_tag_data = get_extended( $post->post_content );
218
-
219
  // Get text before the more(<!--more-->) tag.
220
  $text_before_more_tag = $more_tag_data['main'];
221
  $text_before_more_tag = strip_tags( strip_shortcodes( $text_before_more_tag ) );
@@ -231,7 +231,7 @@ class ES_Handle_Post_Notification {
231
  if ( strpos( $es_templ_body, '{{POSTCATS}}' ) >= 0 ) {
232
  $taxonomies = get_object_taxonomies( $post );
233
  $post_cats = array();
234
-
235
  if ( ! empty( $taxonomies ) ) {
236
  foreach ( $taxonomies as $taxonomy ) {
237
  $taxonomy_object = get_taxonomy( $taxonomy );
129
 
130
  // Add entry into mailing queue table
131
  $mailing_queue_id = ES_DB_Mailing_Queue::add_notification( $data );
132
+
133
  if ( $mailing_queue_id ) {
134
  $mailing_queue_hash = $guid;
135
  $campaign_id = $notification['id'];
161
  }
162
 
163
  public static function prepare_body( $es_templ_body, $post_id, $email_template_id ) {
164
+ $post = get_post( $post_id );
165
+ $post_key = 'post';
166
  // Making $post as global using $GLOBALS['post'] key. Can't use 'post' key directly into $GLOBALS since PHPCS throws global variable assignment warning for 'post'.
167
  $GLOBALS[ $post_key ] = $post;
168
 
169
+ $post_date = ES_Common::convert_date_to_wp_date( $post->post_modified );
170
+ $es_templ_body = str_replace( '{{DATE}}', $post_date, $es_templ_body );
171
 
172
  $post_title = get_the_title( $post );
173
  $es_templ_body = str_replace( '{{POSTTITLE}}', $post_title, $es_templ_body );
215
  $es_templ_body = str_replace( '{{POSTEXCERPT}}', $post_excerpt, $es_templ_body );
216
 
217
  $more_tag_data = get_extended( $post->post_content );
218
+
219
  // Get text before the more(<!--more-->) tag.
220
  $text_before_more_tag = $more_tag_data['main'];
221
  $text_before_more_tag = strip_tags( strip_shortcodes( $text_before_more_tag ) );
231
  if ( strpos( $es_templ_body, '{{POSTCATS}}' ) >= 0 ) {
232
  $taxonomies = get_object_taxonomies( $post );
233
  $post_cats = array();
234
+
235
  if ( ! empty( $taxonomies ) ) {
236
  foreach ( $taxonomies as $taxonomy ) {
237
  $taxonomy_object = get_taxonomy( $taxonomy );
lite/includes/classes/class-es-handle-subscription.php CHANGED
@@ -20,7 +20,6 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
20
  *
21
  * @since 4.0.0
22
  * @var
23
- *
24
  */
25
  public $email;
26
 
@@ -29,7 +28,6 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
29
  *
30
  * @since 4.0.0
31
  * @var
32
- *
33
  */
34
  public $name;
35
 
@@ -38,7 +36,6 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
38
  *
39
  * @since 4.0.0
40
  * @var
41
- *
42
  */
43
  public $first_name;
44
 
@@ -47,7 +44,6 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
47
  *
48
  * @since 4.0.0
49
  * @var
50
- *
51
  */
52
  public $last_name;
53
 
@@ -56,25 +52,22 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
56
  *
57
  * @since 4.0.0
58
  * @var
59
- *
60
  */
61
  public $es_optin_type;
62
 
63
  /**
64
- * List Id
65
  *
66
  * @since 4.0.0
67
  * @var
68
- *
69
  */
70
  public $list_ids;
71
 
72
  /**
73
- * List Hashes
74
  *
75
  * @since 4.6.12
76
  * @var
77
- *
78
  */
79
  public $list_hashes;
80
 
@@ -83,52 +76,46 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
83
  *
84
  * @since 4.0.0
85
  * @var
86
- *
87
  */
88
  public $es_nonce;
89
-
90
  /**
91
  * Subscriber Status
92
  *
93
  * @since 4.0.0
94
  * @var
95
- *
96
  */
97
  public $status;
98
-
99
  /**
100
  * To check if double-optin or not
101
  *
102
  * @since 4.0.0
103
  * @var
104
- *
105
  */
106
  public $is_double_optin = false;
107
-
108
  /**
109
  * Guid
110
  *
111
  * @since 4.0.0
112
  * @var
113
- *
114
  */
115
  public $guid;
116
-
117
  /**
118
  * Database Id
119
  *
120
  * @since 4.0.0
121
  * @var
122
- *
123
  */
124
  public $db_id;
125
-
126
  /**
127
  * Form id
128
  *
129
  * @since 4.0.0
130
  * @var
131
- *
132
  */
133
  public $form_id;
134
 
@@ -137,16 +124,14 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
137
  *
138
  * @since 4.7.3
139
  * @var
140
- *
141
  */
142
  public $ip_address;
143
-
144
  /**
145
  * If the user is subscribed from Rainmaker
146
  *
147
  * @since 4.0.0
148
  * @var
149
- *
150
  */
151
  private $from_rainmaker = false;
152
 
@@ -174,8 +159,11 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
174
  * @param array $external_form_data data from external form/APIs.
175
  *
176
  * @since 4.0.0
177
- *
178
  * @modified 4.5.7 Added $external_form_data parameter.
 
 
 
179
  */
180
  public function process_request( $external_form_data = array() ) {
181
 
@@ -188,11 +176,12 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
188
  $es_subscribe = ! empty( $_POST['esfpx_es-subscribe'] ) ? sanitize_text_field( wp_unslash( $_POST['esfpx_es-subscribe'] ) ) : '';
189
 
190
  if ( ! empty( $es_subscribe ) && wp_verify_nonce( $es_subscribe, 'es-subscribe' ) ) {
191
- //TODO: Verify Nonce
192
  $nonce_verified = true;
193
  }
194
 
195
- $doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
 
196
 
197
  // Verify nonce only if it is submitted through Email Subscribers' subscription form else check if we have form data in $external_form_data.
198
  if ( ( 'subscribe' === $es ) || ! empty( $external_form_data ) ) {
@@ -215,19 +204,21 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
215
  }
216
 
217
  $response = $this->do_response( $validate_response );
218
- if ( $doing_ajax ) {
 
 
219
  wp_send_json( $response );
220
  } else {
221
  return $response;
222
  }
223
  }
224
 
225
- $email = ! empty( $form_data['esfpx_email'] ) ? sanitize_email( $form_data['esfpx_email'] ) : '';
226
- $name = ! empty( $form_data['esfpx_name'] ) ? sanitize_text_field( $form_data['esfpx_name'] ) : '';
227
- $ip_address = ! empty( $form_data['esfpx_ip_address'] ) ? sanitize_text_field( $form_data['esfpx_ip_address'] ) : '';
228
 
229
  $first_name = '';
230
- $last_name = '';
231
  if ( ! empty( $name ) ) {
232
  // Get First Name and Last Name from Name.
233
  $name_parts = ES_Common::prepare_first_name_last_name( $name );
@@ -260,7 +251,7 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
260
  $this->list_ids = ES()->lists_db->get_column_by_condition( 'id', $where );
261
 
262
  if ( ! empty( $this->list_ids ) ) {
263
-
264
  $is_new = true;
265
  /**
266
  * Check if subscribers exists?
@@ -286,7 +277,9 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
286
  $data = apply_filters( 'ig_es_add_subscriber_data', $data );
287
  if ( 'ERROR' === $data['status'] ) {
288
  $response = $this->do_response( $validate_response );
289
- if ( $doing_ajax ) {
 
 
290
  wp_send_json( $response );
291
  } else {
292
  return $response;
@@ -304,8 +297,10 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
304
  $contact_lists = ES()->lists_contacts_db->get_list_ids_by_contact( $contact_id, 'subscribed' );
305
  if ( empty( array_diff( $this->list_ids, $contact_lists ) ) ) {
306
  $response['message'] = 'es_email_exists_notice';
307
- $response = $this->do_response( $response );
308
- if ( $doing_ajax ) {
 
 
309
  wp_send_json( $response );
310
  } else {
311
  return $response;
@@ -321,7 +316,7 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
321
  $data['first_name'] = $this->first_name;
322
  $data['last_name'] = $this->last_name;
323
  }
324
-
325
  if ( ! empty( $this->ip_address ) ) {
326
  $data['ip_address'] = $this->ip_address;
327
  }
@@ -360,7 +355,7 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
360
  'last_name' => $this->last_name,
361
  'guid' => $this->guid,
362
  'list_name' => $list_name,
363
- 'list_ids' => $this->list_ids,
364
  );
365
 
366
  if ( $this->is_double_optin ) {
@@ -384,8 +379,10 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
384
  } else {
385
  $response['status'] = 'SUCCESS';
386
  $response['message'] = 'es_optin_success_message';
387
- $response = $this->do_response( $response );
388
- if ( $doing_ajax ) {
 
 
389
  wp_send_json( $response );
390
  } else {
391
  return $response;
@@ -393,8 +390,10 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
393
  }
394
  } else {
395
  $response['message'] = 'es_no_list_selected';
396
- $response = $this->do_response( $response );
397
- if ( $doing_ajax ) {
 
 
398
  wp_send_json( $response );
399
  } else {
400
  return $response;
@@ -406,7 +405,9 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
406
 
407
  $response = $this->do_response( $response );
408
 
409
- if ( $doing_ajax ) {
 
 
410
  wp_send_json( $response );
411
  } else {
412
  return $response;
@@ -450,7 +451,7 @@ if ( ! class_exists( 'ES_Handle_Subscription' ) ) {
450
  if ( ! $this->from_rainmaker ) {
451
 
452
  // Honeypot validation
453
- //$hp_key = "esfpx_es_hp" . wp_create_nonce( 'es_hp' );
454
  $hp_key = 'esfpx_es_hp_email';
455
  if ( ! isset( $data[ $hp_key ] ) || ! empty( $data[ $hp_key ] ) ) {
456
  $es_response['message'] = 'es_unexpected_error_notice';
20
  *
21
  * @since 4.0.0
22
  * @var
 
23
  */
24
  public $email;
25
 
28
  *
29
  * @since 4.0.0
30
  * @var
 
31
  */
32
  public $name;
33
 
36
  *
37
  * @since 4.0.0
38
  * @var
 
39
  */
40
  public $first_name;
41
 
44
  *
45
  * @since 4.0.0
46
  * @var
 
47
  */
48
  public $last_name;
49
 
52
  *
53
  * @since 4.0.0
54
  * @var
 
55
  */
56
  public $es_optin_type;
57
 
58
  /**
59
+ * List Id
60
  *
61
  * @since 4.0.0
62
  * @var
 
63
  */
64
  public $list_ids;
65
 
66
  /**
67
+ * List Hashes
68
  *
69
  * @since 4.6.12
70
  * @var
 
71
  */
72
  public $list_hashes;
73
 
76
  *
77
  * @since 4.0.0
78
  * @var
 
79
  */
80
  public $es_nonce;
81
+
82
  /**
83
  * Subscriber Status
84
  *
85
  * @since 4.0.0
86
  * @var
 
87
  */
88
  public $status;
89
+
90
  /**
91
  * To check if double-optin or not
92
  *
93
  * @since 4.0.0
94
  * @var
 
95
  */
96
  public $is_double_optin = false;
97
+
98
  /**
99
  * Guid
100
  *
101
  * @since 4.0.0
102
  * @var
 
103
  */
104
  public $guid;
105
+
106
  /**
107
  * Database Id
108
  *
109
  * @since 4.0.0
110
  * @var
 
111
  */
112
  public $db_id;
113
+
114
  /**
115
  * Form id
116
  *
117
  * @since 4.0.0
118
  * @var
 
119
  */
120
  public $form_id;
121
 
124
  *
125
  * @since 4.7.3
126
  * @var
 
127
  */
128
  public $ip_address;
129
+
130
  /**
131
  * If the user is subscribed from Rainmaker
132
  *
133
  * @since 4.0.0
134
  * @var
 
135
  */
136
  private $from_rainmaker = false;
137
 
159
  * @param array $external_form_data data from external form/APIs.
160
  *
161
  * @since 4.0.0
162
+ *
163
  * @modified 4.5.7 Added $external_form_data parameter.
164
+ * @modified 4.8.2 Added IG_ES_RETURN_HANDLE_RESPONSE const.
165
+ *
166
+ * @return void | array
167
  */
168
  public function process_request( $external_form_data = array() ) {
169
 
176
  $es_subscribe = ! empty( $_POST['esfpx_es-subscribe'] ) ? sanitize_text_field( wp_unslash( $_POST['esfpx_es-subscribe'] ) ) : '';
177
 
178
  if ( ! empty( $es_subscribe ) && wp_verify_nonce( $es_subscribe, 'es-subscribe' ) ) {
179
+ // TODO: Verify Nonce
180
  $nonce_verified = true;
181
  }
182
 
183
+ $doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
184
+ $return_response = defined( 'IG_ES_RETURN_HANDLE_RESPONSE' ) && IG_ES_RETURN_HANDLE_RESPONSE;
185
 
186
  // Verify nonce only if it is submitted through Email Subscribers' subscription form else check if we have form data in $external_form_data.
187
  if ( ( 'subscribe' === $es ) || ! empty( $external_form_data ) ) {
204
  }
205
 
206
  $response = $this->do_response( $validate_response );
207
+ if ( $return_response ) {
208
+ return $response;
209
+ } elseif ( $doing_ajax ) {
210
  wp_send_json( $response );
211
  } else {
212
  return $response;
213
  }
214
  }
215
 
216
+ $email = ! empty( $form_data['esfpx_email'] ) ? sanitize_email( $form_data['esfpx_email'] ) : '';
217
+ $name = ! empty( $form_data['esfpx_name'] ) ? sanitize_text_field( $form_data['esfpx_name'] ) : '';
218
+ $ip_address = ! empty( $form_data['esfpx_ip_address'] ) ? sanitize_text_field( $form_data['esfpx_ip_address'] ) : '';
219
 
220
  $first_name = '';
221
+ $last_name = '';
222
  if ( ! empty( $name ) ) {
223
  // Get First Name and Last Name from Name.
224
  $name_parts = ES_Common::prepare_first_name_last_name( $name );
251
  $this->list_ids = ES()->lists_db->get_column_by_condition( 'id', $where );
252
 
253
  if ( ! empty( $this->list_ids ) ) {
254
+
255
  $is_new = true;
256
  /**
257
  * Check if subscribers exists?
277
  $data = apply_filters( 'ig_es_add_subscriber_data', $data );
278
  if ( 'ERROR' === $data['status'] ) {
279
  $response = $this->do_response( $validate_response );
280
+ if ( $return_response ) {
281
+ return $response;
282
+ } elseif ( $doing_ajax ) {
283
  wp_send_json( $response );
284
  } else {
285
  return $response;
297
  $contact_lists = ES()->lists_contacts_db->get_list_ids_by_contact( $contact_id, 'subscribed' );
298
  if ( empty( array_diff( $this->list_ids, $contact_lists ) ) ) {
299
  $response['message'] = 'es_email_exists_notice';
300
+ $response = $this->do_response( $response );
301
+ if ( $return_response ) {
302
+ return $response;
303
+ } elseif ( $doing_ajax ) {
304
  wp_send_json( $response );
305
  } else {
306
  return $response;
316
  $data['first_name'] = $this->first_name;
317
  $data['last_name'] = $this->last_name;
318
  }
319
+
320
  if ( ! empty( $this->ip_address ) ) {
321
  $data['ip_address'] = $this->ip_address;
322
  }
355
  'last_name' => $this->last_name,
356
  'guid' => $this->guid,
357
  'list_name' => $list_name,
358
+ 'list_ids' => $this->list_ids,
359
  );
360
 
361
  if ( $this->is_double_optin ) {
379
  } else {
380
  $response['status'] = 'SUCCESS';
381
  $response['message'] = 'es_optin_success_message';
382
+ $response = $this->do_response( $response );
383
+ if ( $return_response ) {
384
+ return $response;
385
+ } elseif ( $doing_ajax ) {
386
  wp_send_json( $response );
387
  } else {
388
  return $response;
390
  }
391
  } else {
392
  $response['message'] = 'es_no_list_selected';
393
+ $response = $this->do_response( $response );
394
+ if ( $return_response ) {
395
+ return $response;
396
+ } elseif ( $doing_ajax ) {
397
  wp_send_json( $response );
398
  } else {
399
  return $response;
405
 
406
  $response = $this->do_response( $response );
407
 
408
+ if ( $return_response ) {
409
+ return $response;
410
+ } elseif ( $doing_ajax ) {
411
  wp_send_json( $response );
412
  } else {
413
  return $response;
451
  if ( ! $this->from_rainmaker ) {
452
 
453
  // Honeypot validation
454
+ // $hp_key = "esfpx_es_hp" . wp_create_nonce( 'es_hp' );
455
  $hp_key = 'esfpx_es_hp_email';
456
  if ( ! isset( $data[ $hp_key ] ) || ! empty( $data[ $hp_key ] ) ) {
457
  $es_response['message'] = 'es_unexpected_error_notice';
lite/includes/classes/class-es-handle-sync-wp-user.php CHANGED
@@ -68,18 +68,18 @@ class ES_Handle_Sync_Wp_User {
68
  </th>
69
  <td>
70
  <select name="form_data[es_registered]" id="es_email_status">
71
- <option value='NO'
72
- <?php
73
  if ('NO' == $form_data['es_registered'] ) {
74
  echo "selected='selected'";
75
- }
76
  ?>
77
  ><?php esc_html_e( 'No', 'email-subscribers' ); ?></option>
78
- <option value='YES'
79
- <?php
80
  if ( 'YES' == $form_data['es_registered'] ) {
81
  echo "selected='selected'";
82
- }
83
  ?>
84
  ><?php esc_html_e( 'Yes', 'email-subscribers' ); ?></option>
85
  </select>
@@ -94,9 +94,9 @@ class ES_Handle_Sync_Wp_User {
94
  </th>
95
  <td>
96
  <select name="form_data[es_registered_group]">
97
- <?php
98
- $lists_dropdown = ES_Common::prepare_list_dropdown_options( $form_data['es_registered_group'], 'Select List' );
99
- $allowedtags = ig_es_allowed_html_tags_in_esc();
100
  echo wp_kses( $lists_dropdown , $allowedtags );
101
  ?>
102
  </select>
68
  </th>
69
  <td>
70
  <select name="form_data[es_registered]" id="es_email_status">
71
+ <option value='NO'
72
+ <?php
73
  if ('NO' == $form_data['es_registered'] ) {
74
  echo "selected='selected'";
75
+ }
76
  ?>
77
  ><?php esc_html_e( 'No', 'email-subscribers' ); ?></option>
78
+ <option value='YES'
79
+ <?php
80
  if ( 'YES' == $form_data['es_registered'] ) {
81
  echo "selected='selected'";
82
+ }
83
  ?>
84
  ><?php esc_html_e( 'Yes', 'email-subscribers' ); ?></option>
85
  </select>
94
  </th>
95
  <td>
96
  <select name="form_data[es_registered_group]">
97
+ <?php
98
+ $lists_dropdown = ES_Common::prepare_list_dropdown_options( $form_data['es_registered_group'], 'Select List' );
99
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
100
  echo wp_kses( $lists_dropdown , $allowedtags );
101
  ?>
102
  </select>
lite/includes/classes/class-es-ig-redirect.php CHANGED
@@ -23,16 +23,16 @@ if ( ! class_exists( 'ES_IG_Redirect' ) ) {
23
 
24
  $redirect_url = admin_url( 'post-new.php?post_type=ig_campaign' );
25
  $ig_activate_url = admin_url( 'plugins.php?plugin_status=inactive' );
26
- $plugin_url = 'https://wordpress.org/plugins/icegram';
27
 
28
  if ( 'create_campaign' === $action ) {
29
  $redirect_url = admin_url( 'edit.php?post_type=ig_campaign' );
30
  /* translators: %s: Link to WordPress.org Icegram plugin page */
31
- $info = sprintf( __( 'Create Onsite Campaigns using <a href="%s" target="_blank">Icegram</a>', 'email-subscribers' ), esc_url( $plugin_url ) );
32
  } elseif ( 'create_template' === $action ) {
33
  $redirect_url = admin_url( 'edit.php?ig_campaign&page=icegram-gallery' );
34
  /* translators: %s: Link to WordPress.org Icegram plugin page */
35
- $info = sprintf( __( 'Create Popups using <a href="%s" target="_blank">Icegram</a>', 'email-subscribers' ), esc_url( $plugin_url ) );
36
  }
37
 
38
  $icegram_plugin = 'icegram/icegram.php';
@@ -74,14 +74,14 @@ if ( ! class_exists( 'ES_IG_Redirect' ) ) {
74
  if ( in_array( $icegram_plugin, $inactive_plugins ) ) {
75
  ?>
76
  <a href="<?php echo esc_url( $ig_activate_url ); ?>"><button type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-white text-sm leading-5 font-medium text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue transition ease-in-out duration-150">
77
- <?php
78
  esc_html_e( 'Activate Icegram', 'email-subscribers' );
79
  } else {
80
  ?>
81
  <a href="<?php echo esc_url( $ig_install_url ); ?>"><button type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-white text-sm leading-5 font-medium text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue transition ease-in-out duration-150">
82
- <?php
83
  esc_html_e( 'Install Icegram', 'email-subscribers' );
84
- }
85
  ?>
86
  </button></a>
87
  </span>
@@ -159,7 +159,7 @@ if ( ! class_exists( 'ES_IG_Redirect' ) ) {
159
  </main>
160
  </div>
161
 
162
- <?php
163
  }
164
  }
165
  }
23
 
24
  $redirect_url = admin_url( 'post-new.php?post_type=ig_campaign' );
25
  $ig_activate_url = admin_url( 'plugins.php?plugin_status=inactive' );
26
+ $plugin_url = 'https://wordpress.org/plugins/icegram';
27
 
28
  if ( 'create_campaign' === $action ) {
29
  $redirect_url = admin_url( 'edit.php?post_type=ig_campaign' );
30
  /* translators: %s: Link to WordPress.org Icegram plugin page */
31
+ $info = sprintf( __( 'Create Onsite Campaigns using <a href="%s" target="_blank">Icegram</a>', 'email-subscribers' ), esc_url( $plugin_url ) );
32
  } elseif ( 'create_template' === $action ) {
33
  $redirect_url = admin_url( 'edit.php?ig_campaign&page=icegram-gallery' );
34
  /* translators: %s: Link to WordPress.org Icegram plugin page */
35
+ $info = sprintf( __( 'Create Popups using <a href="%s" target="_blank">Icegram</a>', 'email-subscribers' ), esc_url( $plugin_url ) );
36
  }
37
 
38
  $icegram_plugin = 'icegram/icegram.php';
74
  if ( in_array( $icegram_plugin, $inactive_plugins ) ) {
75
  ?>
76
  <a href="<?php echo esc_url( $ig_activate_url ); ?>"><button type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-white text-sm leading-5 font-medium text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue transition ease-in-out duration-150">
77
+ <?php
78
  esc_html_e( 'Activate Icegram', 'email-subscribers' );
79
  } else {
80
  ?>
81
  <a href="<?php echo esc_url( $ig_install_url ); ?>"><button type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-white text-sm leading-5 font-medium text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue transition ease-in-out duration-150">
82
+ <?php
83
  esc_html_e( 'Install Icegram', 'email-subscribers' );
84
+ }
85
  ?>
86
  </button></a>
87
  </span>
159
  </main>
160
  </div>
161
 
162
+ <?php
163
  }
164
  }
165
  }
lite/includes/classes/class-es-import-subscribers.php CHANGED
@@ -47,7 +47,7 @@ class ES_Import_Subscribers {
47
  }
48
 
49
  public function prepare_import_subscriber_form() {
50
-
51
  if ( is_multisite() && ! is_upload_space_available() ) {
52
  return;
53
  }
@@ -58,15 +58,15 @@ class ES_Import_Subscribers {
58
  'importing_from' => 'csv',
59
  'security' => wp_create_nonce( 'ig-es-admin-ajax-nonce' ),
60
  );
61
-
62
  $upload_action_url = admin_url( 'admin-ajax.php' );
63
- $plupload_init = array(
64
  'browse_button' => 'plupload-browse-button',
65
  'container' => 'plupload-upload-ui',
66
  'drop_element' => 'drag-drop-area',
67
  'file_data_name' => 'async-upload',
68
  'url' => $upload_action_url,
69
- 'filters' => array(
70
  'max_file_size' => $max_upload_size . 'b',
71
  'mime_types' => array( array( 'extensions' => 'csv' ) ),
72
  ),
@@ -120,9 +120,9 @@ class ES_Import_Subscribers {
120
  <?php esc_html_e( 'Select CSV file', 'email-subscribers' ); ?>
121
  </span>
122
  <p class="mt-2 es_helper_text">
123
- <?php
124
  /* translators: %s: Max upload size */
125
- echo sprintf( esc_html__( 'File size should be less than %s', 'email-subscribers' ), esc_html( size_format( $max_upload_size ) ) );
126
  ?>
127
  </p>
128
  <p class="mt-2 es_helper_text">
@@ -180,7 +180,7 @@ class ES_Import_Subscribers {
180
  <p class="es-api-import-status pt-4 text-sm font-medium text-gray-600 tracking-wide hidden">&nbsp;</p>
181
  <div class="clearfix clear mt-10 -mb-4 ">
182
  <button id="es_mailchimp_verify_api_key" class="ig-es-primary-button px-2 py-1" data-callback="verify_api_key">
183
- <?php echo esc_html__('Next', 'email-subscribers'); ?>
184
  &nbsp;
185
  <svg style="display:none" class="es-import-loader mr-1 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
186
  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
@@ -192,7 +192,7 @@ class ES_Import_Subscribers {
192
  </div>
193
  </div>
194
 
195
- <?php
196
  do_action( 'ig_es_subscriber_import_method_tab_content' );
197
  ?>
198
 
@@ -205,7 +205,7 @@ class ES_Import_Subscribers {
205
  <div class="ml-6">
206
  <label for="select_mailchimp_list">
207
  <span class="block pr-4 text-sm font-medium text-gray-600 pb-1">
208
- <?php echo esc_html_e('Select list', 'email-subscribers'); ?>
209
  </span>
210
  <p class="italic text-xs font-normal text-gray-400 mt-2 leading-snug" id="apikey-info-text"><?php esc_html_e( 'Select all the lists that you want to import from MailChimp', 'email-subscribers' ); ?>
211
  </p>
@@ -307,9 +307,9 @@ class ES_Import_Subscribers {
307
  </div>
308
  <div class="w-3/4 mb-6 mr-4 mt-4">
309
  <select class="relative form-select shadow-sm border border-gray-400 sm:w-32 lg:w-48 ml-4" name="es_email_status" id="es_email_status">
310
- <?php
311
  $statuses_dropdown = ES_Common::prepare_statuses_dropdown_options();
312
- echo wp_kses( $statuses_dropdown , $allowedtags );
313
  ?>
314
  </select>
315
  </div>
@@ -339,9 +339,9 @@ class ES_Import_Subscribers {
339
  ?>
340
  <div class="ml-4">
341
  <select name="<?php echo esc_attr( $select_list_name ); ?>" id="list_id" class="relative shadow-sm border border-gray-400 sm:w-32 lg:w-48 <?php echo esc_attr( $select_list_class ); ?>" <?php echo esc_attr( $select_list_attr ); ?>>
342
- <?php
343
  $lists_dropdown = ES_Common::prepare_list_dropdown_options();
344
- echo wp_kses( $lists_dropdown , $allowedtags );
345
  ?>
346
  </select>
347
  </div>
@@ -469,7 +469,7 @@ class ES_Import_Subscribers {
469
 
470
  /**
471
  * Ajax handler to insert import CSV data into temporary table.
472
- *
473
  * @since 4.6.6
474
  */
475
  public function ajax_import_subscribers_upload_handler() {
@@ -501,7 +501,7 @@ class ES_Import_Subscribers {
501
  }
502
 
503
  $importing_from = ig_es_get_request_data( 'importing_from' );
504
- if ( 'csv' === $importing_from && isset( $_FILES['async-upload'] ) ) {
505
  if ( isset( $_FILES['async-upload']['tmp_name'] ) && is_uploaded_file( sanitize_text_field( $_FILES['async-upload']['tmp_name'] ) ) ) {
506
  $tmp_file = sanitize_text_field( $_FILES['async-upload']['tmp_name'] );
507
  $raw_data = file_get_contents( $tmp_file );
@@ -555,10 +555,10 @@ class ES_Import_Subscribers {
555
  );
556
 
557
  if ( ! empty( $users ) ) {
558
- $raw_data = '';
559
  $seperator = ';';
560
  $data_contain_headers = false;
561
-
562
  $headers = array(
563
  __( 'Email', 'email-subscribers' ),
564
  __( 'First Name', 'email-subscribers' ),
@@ -566,33 +566,33 @@ class ES_Import_Subscribers {
566
  __( 'Nick Name', 'email-subscribers' ),
567
  __( 'Display Name', 'email-subscribers' ),
568
  );
569
-
570
  foreach ( $users as $user ) {
571
-
572
  // User must have a role assigned.
573
  if ( ! $user->_role ) {
574
  continue;
575
  }
576
-
577
  // Role is set but not in the list
578
  if ( ! empty( $roles ) && ! array_intersect( array_keys( unserialize( $user->_role ) ), $roles ) ) {
579
  continue;
580
  }
581
-
582
  $user_data = array();
583
-
584
  foreach ( $user as $key => $data ) {
585
  if ( '_role' === $key ) {
586
  continue;
587
  }
588
-
589
  if ( 'firstname' === $key && ! $data ) {
590
  $data = $user->display_name;
591
  }
592
-
593
  $user_data[] = $data;
594
  }
595
-
596
  $raw_data .= implode( ';', $user_data );
597
  $raw_data .= "\n";
598
  }
@@ -605,17 +605,17 @@ class ES_Import_Subscribers {
605
  if ( empty( $raw_data ) ) {
606
  wp_send_json( $response );
607
  }
608
-
609
- $response = self::insert_into_temp_table( $raw_data, $seperator, $data_contain_headers, $headers, '', $importing_from );
610
  $response['success'] = true;
611
  $response['memoryusage'] = size_format( memory_get_peak_usage( true ), 2 );
612
-
613
  wp_send_json( $response );
614
  }
615
 
616
  /**
617
  * Ajax handler to get import data from temporary table.
618
- *
619
  * @since 4.6.6
620
  */
621
  public function ajax_get_import_data() {
@@ -630,13 +630,13 @@ class ES_Import_Subscribers {
630
 
631
  $identifier = '';
632
  if ( isset( $_POST['identifier'] ) ) {
633
- $identifier = sanitize_text_field( $_POST['identifier'] );
634
  }
635
 
636
  if ( ! empty( $identifier ) ) {
637
-
638
  $response['identifier'] = $identifier;
639
- $response['data'] = get_option( 'ig_es_bulk_import' );
640
  // get first and last entry
641
  $entries = $wpdb->get_row(
642
  $wpdb->prepare(
@@ -653,7 +653,7 @@ class ES_Import_Subscribers {
653
  $data = str_getcsv( $first[0], $response['data']['separator'], '"' );
654
  $cols = count( $data );
655
  $contactcount = $response['data']['lines'];
656
- $fields = array(
657
  'email' => __( 'Email', 'email-subscribers' ),
658
  'first_name' => __( 'First Name', 'email-subscribers' ),
659
  'last_name' => __( 'Last Name', 'email-subscribers' ),
@@ -661,7 +661,7 @@ class ES_Import_Subscribers {
661
  'last_first' => __( '(Last Name) (First Name)', 'email-subscribers' ),
662
  'created_at' => __( 'Subscribed at', 'email-subscribers' ),
663
  );
664
- if ( ! empty( $response['data']['importing_from'] ) && 'wordpress_users' !== $response['data']['importing_from'] ) {
665
  $fields['list_name'] = __( 'List Name', 'email-subscribers' );
666
  $fields['status'] = __( 'Status', 'email-subscribers' );
667
  }
@@ -680,7 +680,7 @@ class ES_Import_Subscribers {
680
 
681
  </label>
682
  </div>
683
- </div>' ;
684
  $html .= '<div class="w-3/4 mx-4 border-b border-gray-200 shadow rounded-lg"><table class="w-full bg-white rounded-lg shadow overflow-hidden ">';
685
  $html .= '<thead><tr class="border-b border-gray-200 bg-gray-50 text-left text-sm leading-4 font-medium text-gray-500 tracking-wider"><th class="pl-3 py-4" style="width:20px;">#</th>';
686
  $phpmailer = ES()->mailer->get_phpmailer();
@@ -703,10 +703,10 @@ class ES_Import_Subscribers {
703
  $is_selected = true;
704
  } elseif ( ! empty( $headers[ $i ] ) ) {
705
  if ( strip_tags( $headers[ $i ] ) === $fields[ $key ] ) {
706
- $is_selected = ( 'first_name' === $key ) || ( 'last_name' === $key ) || ( 'list_name' === $key && 'mailchimp-api' === $response['data']['importing_from'] ) || ( 'status' === $key && 'mailchimp-api' === $response['data']['importing_from'] );
707
  }
708
  }
709
- $select .= '<option value="' . $key . '" ' . ( $is_selected ? 'selected' : '' ) . '>' . $value . '</option>';
710
  }
711
  $select .= '</select>';
712
  $html .= '<th class="pl-3 py-4 font-medium">' . $select . '</th>';
@@ -721,7 +721,7 @@ class ES_Import_Subscribers {
721
  }
722
  $html .= '</thead><tbody>';
723
  for ( $i = 0; $i < min( 3, $contactcount ); $i++ ) {
724
- $data = str_getcsv( ( $first[ $i ] ), $response['data']['separator'], '"' );
725
  $html .= '<tr class="border-b border-gray-200 text-left text-sm leading-4 text-gray-500 tracking-wide"><td class="pl-3">' . number_format_i18n( $i + 1 ) . '</td>';
726
  foreach ( $data as $cell ) {
727
  if ( ! empty( $cell ) && is_email( $cell ) ) {
@@ -752,7 +752,7 @@ class ES_Import_Subscribers {
752
  $html .= '</div></div>';
753
 
754
  $response['html'] = $html;
755
- $response['success'] = true;
756
  }
757
 
758
  wp_send_json( $response );
@@ -760,7 +760,7 @@ class ES_Import_Subscribers {
760
 
761
  /**
762
  * Ajax handler to import subscirbers from temporary table
763
- *
764
  * @since 4.6.6
765
  */
766
  public function ajax_do_import() {
@@ -796,17 +796,17 @@ class ES_Import_Subscribers {
796
  if ( isset( $_POST['options'] ) ) {
797
  $bulkdata = ig_es_get_data( $_POST, 'options', array() );
798
  }
799
-
800
- $bulkdata = wp_parse_args( $bulkdata, get_option( 'ig_es_bulk_import' ) );
801
- $erroremails = get_option( 'ig_es_bulk_import_errors', array() );
802
- $order = isset( $bulkdata['mapping_order'] ) ? $bulkdata['mapping_order'] : array();
803
- $list_id = isset( $bulkdata['list_id'] ) ? $bulkdata['list_id'] : array();
804
- $parts_at_once = 10;
805
  $selected_status = $bulkdata['status'];
806
-
807
  $error_codes = array(
808
- 'invalid' => __( 'Email address is invalid.', 'email-subscribers' ),
809
- 'empty' => __( 'Email address is empty.', 'email-subscribers' ),
810
  );
811
 
812
  if ( ! empty( $list_id ) && ! is_array( $list_id ) ) {
@@ -816,7 +816,7 @@ class ES_Import_Subscribers {
816
  if ( isset( $_POST['id'] ) ) {
817
 
818
  $bulkdata['current'] = (int) sanitize_text_field( $_POST['id'] );
819
- $raw_list_data = $wpdb->get_col(
820
  $wpdb->prepare(
821
  "SELECT data FROM {$wpdb->prefix}ig_temp_import
822
  WHERE identifier = %s ORDER BY ID ASC LIMIT %d, %d",
@@ -834,12 +834,12 @@ class ES_Import_Subscribers {
834
  $processed_emails = ! empty( $bulkdata['processed_emails'] ) ? $bulkdata['processed_emails'] : array();
835
  $list_contact_data = array();
836
  $es_status_mapping = array(
837
- __( 'Subscribed', 'email-subscribers' ) => 'subscribed',
838
- __( 'Unsubscribed', 'email-subscribers' ) => 'unsubscribed',
839
- __( 'Unconfirmed', 'email-subscribers' ) => 'unconfirmed',
840
- __( 'Hard Bounced', 'email-subscribers' ) => 'hard_bounced' ,
841
  );
842
-
843
  foreach ( $raw_list_data as $raw_list ) {
844
  $raw_list = unserialize( base64_decode( $raw_list ) );
845
  // each entry
@@ -858,12 +858,12 @@ class ES_Import_Subscribers {
858
  }
859
  switch ( $order[ $col ] ) {
860
  case 'email':
861
- $insert[ 'email' ] = $d;
862
  // Convert special characters in the email domain name to ascii.
863
  if ( is_callable( array( $phpmailer, 'punyencodeAddress' ) ) ) {
864
  $encoded_email = $phpmailer->punyencodeAddress( $insert['email'] );
865
  if ( ! empty( $encoded_email ) ) {
866
- $insert[ 'email' ] = $encoded_email;
867
  }
868
  }
869
  break;
@@ -873,7 +873,7 @@ class ES_Import_Subscribers {
873
  $insert['first_name'] = $name[0];
874
  }
875
  if ( ! empty( $name[1] ) ) {
876
- $insert['last_name'] = $name[1];
877
  }
878
  break;
879
  case 'last_first':
@@ -882,12 +882,12 @@ class ES_Import_Subscribers {
882
  $insert['first_name'] = $name[1];
883
  }
884
  if ( ! empty( $name[0] ) ) {
885
- $insert['last_name'] = $name[0];
886
  }
887
  break;
888
  case 'created_at':
889
  if ( ! is_numeric( $d ) && ! empty( $d ) ) {
890
- $d = sanitize_text_field( $d );
891
  $insert['created_at'] = gmdate( 'Y-m-d H:i:s', strtotime( $d ) - $gmt_offset );
892
  }
893
  break;
@@ -898,7 +898,7 @@ class ES_Import_Subscribers {
898
  $insert[ $order[ $col ] ] = $d;
899
  }
900
  }
901
-
902
  if ( empty( $insert['email'] ) || ! is_email( $insert['email'] ) ) {
903
  $error_data = array();
904
  if ( empty( $insert['email'] ) ) {
@@ -926,13 +926,13 @@ class ES_Import_Subscribers {
926
 
927
  $guid = ES_Common::generate_guid();
928
 
929
- $contacts_data[$email]['first_name'] = $first_name;
930
- $contacts_data[$email]['last_name'] = $last_name;
931
- $contacts_data[$email]['email'] = $email;
932
- $contacts_data[$email]['source'] = 'import';
933
- $contacts_data[$email]['status'] = 'verified';
934
- $contacts_data[$email]['hash'] = $guid;
935
- $contacts_data[$email]['created_at'] = $created_at;
936
 
937
  $bulkdata['imported']++;
938
  } else {
@@ -942,22 +942,21 @@ class ES_Import_Subscribers {
942
  $list_names = isset( $insert['list_name'] ) ? sanitize_text_field( trim( $insert['list_name'] ) ) : '';
943
  if ( empty( $insert['list_name'] ) ) {
944
  $list_names_arr = ES()->lists_db->get_lists_by_id( $list_id );
945
- $list_names = implode( ',', array_column( $list_names_arr, 'name' ));
946
  }
947
 
948
  $status = 'unconfirmed';
949
- $list_names = array_map( 'trim', explode( ',', $list_names) );
950
 
951
-
952
  if ( isset( $insert['status'] ) ) {
953
  $map_status = strtolower( str_replace( ' ', '_', $insert['status'] ) );
954
  }
955
-
956
- if ( isset( $insert['status'] ) && in_array( $map_status, $es_status_mapping ) ) {
957
  $status = sanitize_text_field( trim( $map_status ) );
958
  } elseif ( ! empty( $selected_status ) ) {
959
  $status = $selected_status;
960
- }
961
 
962
  if ( ! empty( $es_status_mapping[ $status ] ) ) {
963
  $status = $es_status_mapping[ $status ];
@@ -965,21 +964,21 @@ class ES_Import_Subscribers {
965
 
966
  foreach ( $list_names as $key => $list_name ) {
967
  if ( ! empty( $list_name ) ) {
968
- $list_contact_data[$list_name][$status][] = $email;
969
  }
970
  }
971
 
972
  $current_batch_emails[] = $email;
973
  }
974
  }
975
-
976
  if ( count( $current_batch_emails ) > 0 ) {
977
 
978
  $current_batch_emails = array_unique( $current_batch_emails );
979
 
980
  $existing_contacts_email_id_map = ES()->contacts_db->get_email_id_map( $current_batch_emails );
981
  if ( ! empty( $existing_contacts_email_id_map ) ) {
982
- $contacts_data = array_diff_key( $contacts_data, $existing_contacts_email_id_map );
983
  }
984
 
985
  if ( ! empty( $contacts_data ) ) {
@@ -987,31 +986,31 @@ class ES_Import_Subscribers {
987
  }
988
 
989
  if ( ! empty( $list_contact_data ) ) {
990
- foreach ($list_contact_data as $list_name => $list_data ) {
991
  $list = ES()->lists_db->get_list_by_name( $list_name );
992
-
993
  if ( ! empty( $list ) ) {
994
  $list_id = $list['id'];
995
  } else {
996
  $list_id = ES()->lists_db->add_list( $list_name );
997
  }
998
 
999
- foreach ($list_data as $status => $contact_emails) {
1000
  $contact_id_date = ES()->contacts_db->get_contact_ids_created_at_date_by_emails( $contact_emails );
1001
- $contact_ids = array_keys( $contact_id_date );
1002
  if ( count( $contact_ids ) > 0 ) {
1003
  ES()->lists_contacts_db->remove_contacts_from_lists( $contact_ids, $list_id );
1004
  ES()->lists_contacts_db->do_import_contacts_into_list( $list_id, $contact_id_date, $status, 1 );
1005
  }
1006
  }
1007
  }
1008
- }
1009
  }
1010
  }
1011
 
1012
  $return['memoryusage'] = size_format( memory_get_peak_usage( true ), 2 );
1013
- $return['errors'] = isset( $bulkdata['errors'] ) ? $bulkdata['errors'] : 0;
1014
- $return['duplicate_emails_count'] = isset( $bulkdata['duplicate_emails_count'] ) ? $bulkdata['duplicate_emails_count']: 0;
1015
  $return['imported'] = ( $bulkdata['imported'] );
1016
  $return['total'] = ( $bulkdata['lines'] );
1017
  $return['f_errors'] = number_format_i18n( $bulkdata['errors'] );
@@ -1026,15 +1025,15 @@ class ES_Import_Subscribers {
1026
  $return['html'] .= '<p class="text-base text-gray-600 pt-2 pb-1.5">' . sprintf( esc_html__( '%1$s of %2$s contacts imported.', 'email-subscribers' ), '<span class="font-medium">' . number_format_i18n( $bulkdata['imported'] ) . '</span>', '<span class="font-medium">' . number_format_i18n( $bulkdata['lines'] ) . '</span>' );
1027
 
1028
  if ( $bulkdata['duplicate_emails_count'] ) {
1029
- $duplicate_email_string = _n( 'email', 'emails', $bulkdata['duplicate_emails_count'], 'email-subscribers' );
1030
  /* translators: 1. Duplicate emails count. 2. Email or emails string based on duplicate email count. */
1031
  $return['html'] .= sprintf( esc_html__( '%1$s duplicate %2$s found.', 'email-subscribers' ), '<span class="font-medium">' . number_format_i18n( $bulkdata['duplicate_emails_count'] ) . '</span>', $duplicate_email_string );
1032
  }
1033
  $return['html'] .= '</p>';
1034
  if ( $bulkdata['errors'] ) {
1035
- $i = 0;
1036
  $skipped_contact_string = _n( 'contact was', 'contacts were', $bulkdata['errors'], 'email-subscribers' );
1037
-
1038
  /* translators: %d Skipped emails count %s Skipped contacts string */
1039
  $table = '<p class="text-sm text-gray-600 pt-2 pb-1.5">' . __( sprintf( 'The following %d %s skipped', $bulkdata['errors'], $skipped_contact_string ), 'email-subscribers' ) . ':</p>';
1040
  $table .= '<table class="w-full bg-white rounded-lg shadow overflow-hidden mt-1.5">';
@@ -1049,7 +1048,7 @@ class ES_Import_Subscribers {
1049
  if ( $last_name_column_choosen ) {
1050
  $table .= '<th class="pl-3 py-3 font-medium">' . esc_html__( 'Last Name', 'email-subscribers' ) . '</th>';
1051
  }
1052
-
1053
  $table .= '<th class="pl-3 py-3 font-medium">' . esc_html__( 'Email', 'email-subscribers' ) . '</th>';
1054
  $table .= '<th class="pl-3 pr-1 py-3 font-medium">' . esc_html__( 'Reason', 'email-subscribers' ) . '</th>';
1055
  $table .= '</tr></thead><tbody>';
@@ -1066,7 +1065,7 @@ class ES_Import_Subscribers {
1066
  $table .= '<td class="pl-3 py-3">' . esc_html( $last_name ) . '</td>';
1067
  }
1068
  $error_code = ! empty( $error_data['cd'] ) ? $error_data['cd'] : '-';
1069
- $reason = ! empty( $error_codes[$error_code] ) ? $error_codes[$error_code] : '-';
1070
  $table .= '<td class="pl-3 py-3">' . esc_html( $email ) . '</td><td class="pl-3 py-3">' . esc_html( $reason ) . '</td></tr>';
1071
  }
1072
  $table .= '</tbody></table>';
@@ -1075,7 +1074,7 @@ class ES_Import_Subscribers {
1075
  do_action( 'ig_es_remove_import_data' );
1076
  } else {
1077
  // Add current batch emails into the processed email list
1078
- $processed_emails = array_merge( $processed_emails, $current_batch_emails );
1079
  $bulkdata['processed_emails'] = $processed_emails;
1080
 
1081
  update_option( 'ig_es_bulk_import', $bulkdata );
@@ -1089,11 +1088,11 @@ class ES_Import_Subscribers {
1089
 
1090
  /**
1091
  * Method to truncate temp import table and options used during import process
1092
- *
1093
  * @param string import identifier
1094
- *
1095
  * @since 4.6.6
1096
- *
1097
  * @since 4.7.5 Renamed the function, converted to static method
1098
  */
1099
  public static function remove_import_data( $identifier = '' ) {
@@ -1106,16 +1105,15 @@ class ES_Import_Subscribers {
1106
  delete_option( 'ig_es_bulk_import' );
1107
  delete_option( 'ig_es_bulk_import_errors' );
1108
 
1109
- // We are trancating table so that primary key is reset to 1 otherwise ID column's value will increase on every insert and at some point ID column's data type may not be able to accomodate its value resulting in insert to fail.
1110
  $wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}ig_temp_import" );
1111
  }
1112
 
1113
-
1114
  }
1115
 
1116
  public function api() {
1117
 
1118
- $mailchimp_apikey = ig_es_get_request_data('mailchimp_api_key');
1119
  if ( ! $this->api ) {
1120
  $this->api = new ES_Mailchimp_API( $mailchimp_apikey );
1121
  }
@@ -1138,11 +1136,11 @@ class ES_Import_Subscribers {
1138
  );
1139
  break;
1140
  case 'import_list':
1141
- $limit = ig_es_get_request_data('limit');
1142
- $offset = ig_es_get_request_data('offset');
1143
- $contact_status = ig_es_get_request_data('status');
1144
- $import_identifier = ig_es_get_request_data('identifier');
1145
-
1146
  if ( ! isset( $_POST['id'] ) ) {
1147
  wp_send_json_error(
1148
  array(
@@ -1151,11 +1149,11 @@ class ES_Import_Subscribers {
1151
  );
1152
  }
1153
 
1154
- $limit = isset( $limit ) ? (int) $limit : 1000;
1155
- $offset = isset( $offset ) ? (int) $offset : 0;
1156
- $status = isset( $contact_status) ? (array) $contact_status : array( 'subscribed' );
1157
  $identifier = isset( $import_identifier ) ? $import_identifier : '';
1158
- $list_id = ig_es_get_request_data( 'id' );
1159
 
1160
  $subscribers = $this->api()->members(
1161
  $list_id,
@@ -1166,7 +1164,7 @@ class ES_Import_Subscribers {
1166
  )
1167
  );
1168
 
1169
- $list_name = ig_es_get_request_data('list_name');
1170
 
1171
  $importing_from = 'mailchimp-api';
1172
  $raw_data = '';
@@ -1182,10 +1180,10 @@ class ES_Import_Subscribers {
1182
  );
1183
 
1184
  $es_mailchimp_status_mapping = array(
1185
- 'subscribed' => __( 'Subscribed', 'email-subscribers' ),
1186
- 'unsubscribed' => __( 'Unsubscribed', 'email-subscribers' ),
1187
- 'pending' => __( 'Unconfirmed', 'email-subscribers' ),
1188
- 'cleaned' => __( 'Hard Bounced', 'email-subscribers' ),
1189
  );
1190
  foreach ( $subscribers as $subscriber ) {
1191
  if ( ! $subscriber->email_address ) {
@@ -1194,7 +1192,7 @@ class ES_Import_Subscribers {
1194
  $user_data = array();
1195
 
1196
  $list_name = ! empty( $list_name ) ? $list_name : 'Test';
1197
- $status = ! empty( $subscriber->status ) ? $subscriber->status : 'subscribed';
1198
  if ( ! empty( $es_mailchimp_status_mapping[ $status ] ) ) {
1199
  $status = $es_mailchimp_status_mapping[ $status ];
1200
  }
@@ -1213,7 +1211,7 @@ class ES_Import_Subscribers {
1213
  $response = array();
1214
 
1215
  if ( ! empty( $raw_data ) ) {
1216
- $result = self::insert_into_temp_table( $raw_data, $seperator, $data_contain_headers, $headers, $identifier, 'mailchimp-api' );
1217
  $identifier = $result['identifier'];
1218
  }
1219
  $response = array(
@@ -1222,7 +1220,7 @@ class ES_Import_Subscribers {
1222
  'subscribers' => count( $subscribers ),
1223
  'identifier' => $identifier,
1224
  );
1225
-
1226
  wp_send_json_success( $response );
1227
  break;
1228
  case 'verify_api_key':
@@ -1246,35 +1244,34 @@ class ES_Import_Subscribers {
1246
  global $wpdb;
1247
  $raw_data = ( trim( str_replace( array( "\r", "\r\n", "\n\n" ), "\n", $raw_data ) ) );
1248
 
1249
-
1250
  if ( function_exists( 'mb_convert_encoding' ) ) {
1251
  $encoding = mb_detect_encoding( $raw_data, 'auto' );
1252
  } else {
1253
  $encoding = 'UTF-8';
1254
  }
1255
-
1256
  $lines = explode( "\n", $raw_data );
1257
 
1258
  // If data itself contains headers(in case of CSV), then remove it.
1259
  if ( $data_contain_headers ) {
1260
  array_shift( $lines );
1261
  }
1262
-
1263
  $lines_count = count( $lines );
1264
-
1265
  $batch_size = min( 500, max( 200, round( count( $lines ) / 200 ) ) ); // Each entry in temporary import table will have this much of subscribers data
1266
  $parts = array_chunk( $lines, $batch_size );
1267
  $partcount = count( $parts );
1268
 
1269
  do_action( 'ig_es_remove_import_data', $identifier );
1270
 
1271
- $identifier = empty( $identifier ) ? uniqid() : $identifier;
1272
  $response['identifier'] = $identifier;
1273
 
1274
  for ( $i = 0; $i < $partcount; $i++ ) {
1275
 
1276
  $part = $parts[ $i ];
1277
-
1278
  $new_value = base64_encode( serialize( $part ) );
1279
 
1280
  $wpdb->query( $wpdb->prepare( "INSERT INTO {$wpdb->prefix}ig_temp_import (data, identifier) VALUES (%s, %s)", $new_value, $identifier ) );
@@ -1282,10 +1279,10 @@ class ES_Import_Subscribers {
1282
 
1283
  $bulk_import_data = get_option( 'ig_es_bulk_import', array() );
1284
  if ( ! empty( $bulk_import_data ) ) {
1285
- $partcount += $bulk_import_data['parts'];
1286
  $lines_count += $bulk_import_data['lines'];
1287
  }
1288
-
1289
  $bulkimport = array(
1290
  'imported' => 0,
1291
  'errors' => 0,
@@ -1296,7 +1293,7 @@ class ES_Import_Subscribers {
1296
  'separator' => $seperator,
1297
  'importing_from' => $importing_from,
1298
  'data_contain_headers' => $data_contain_headers,
1299
- 'headers' => $headers,
1300
  );
1301
 
1302
  $response['success'] = true;
47
  }
48
 
49
  public function prepare_import_subscriber_form() {
50
+
51
  if ( is_multisite() && ! is_upload_space_available() ) {
52
  return;
53
  }
58
  'importing_from' => 'csv',
59
  'security' => wp_create_nonce( 'ig-es-admin-ajax-nonce' ),
60
  );
61
+
62
  $upload_action_url = admin_url( 'admin-ajax.php' );
63
+ $plupload_init = array(
64
  'browse_button' => 'plupload-browse-button',
65
  'container' => 'plupload-upload-ui',
66
  'drop_element' => 'drag-drop-area',
67
  'file_data_name' => 'async-upload',
68
  'url' => $upload_action_url,
69
+ 'filters' => array(
70
  'max_file_size' => $max_upload_size . 'b',
71
  'mime_types' => array( array( 'extensions' => 'csv' ) ),
72
  ),
120
  <?php esc_html_e( 'Select CSV file', 'email-subscribers' ); ?>
121
  </span>
122
  <p class="mt-2 es_helper_text">
123
+ <?php
124
  /* translators: %s: Max upload size */
125
+ echo sprintf( esc_html__( 'File size should be less than %s', 'email-subscribers' ), esc_html( size_format( $max_upload_size ) ) );
126
  ?>
127
  </p>
128
  <p class="mt-2 es_helper_text">
180
  <p class="es-api-import-status pt-4 text-sm font-medium text-gray-600 tracking-wide hidden">&nbsp;</p>
181
  <div class="clearfix clear mt-10 -mb-4 ">
182
  <button id="es_mailchimp_verify_api_key" class="ig-es-primary-button px-2 py-1" data-callback="verify_api_key">
183
+ <?php echo esc_html__( 'Next', 'email-subscribers' ); ?>
184
  &nbsp;
185
  <svg style="display:none" class="es-import-loader mr-1 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
186
  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
192
  </div>
193
  </div>
194
 
195
+ <?php
196
  do_action( 'ig_es_subscriber_import_method_tab_content' );
197
  ?>
198
 
205
  <div class="ml-6">
206
  <label for="select_mailchimp_list">
207
  <span class="block pr-4 text-sm font-medium text-gray-600 pb-1">
208
+ <?php echo esc_html_e( 'Select list', 'email-subscribers' ); ?>
209
  </span>
210
  <p class="italic text-xs font-normal text-gray-400 mt-2 leading-snug" id="apikey-info-text"><?php esc_html_e( 'Select all the lists that you want to import from MailChimp', 'email-subscribers' ); ?>
211
  </p>
307
  </div>
308
  <div class="w-3/4 mb-6 mr-4 mt-4">
309
  <select class="relative form-select shadow-sm border border-gray-400 sm:w-32 lg:w-48 ml-4" name="es_email_status" id="es_email_status">
310
+ <?php
311
  $statuses_dropdown = ES_Common::prepare_statuses_dropdown_options();
312
+ echo wp_kses( $statuses_dropdown, $allowedtags );
313
  ?>
314
  </select>
315
  </div>
339
  ?>
340
  <div class="ml-4">
341
  <select name="<?php echo esc_attr( $select_list_name ); ?>" id="list_id" class="relative shadow-sm border border-gray-400 sm:w-32 lg:w-48 <?php echo esc_attr( $select_list_class ); ?>" <?php echo esc_attr( $select_list_attr ); ?>>
342
+ <?php
343
  $lists_dropdown = ES_Common::prepare_list_dropdown_options();
344
+ echo wp_kses( $lists_dropdown, $allowedtags );
345
  ?>
346
  </select>
347
  </div>
469
 
470
  /**
471
  * Ajax handler to insert import CSV data into temporary table.
472
+ *
473
  * @since 4.6.6
474
  */
475
  public function ajax_import_subscribers_upload_handler() {
501
  }
502
 
503
  $importing_from = ig_es_get_request_data( 'importing_from' );
504
+ if ( 'csv' === $importing_from && isset( $_FILES['async-upload'] ) ) {
505
  if ( isset( $_FILES['async-upload']['tmp_name'] ) && is_uploaded_file( sanitize_text_field( $_FILES['async-upload']['tmp_name'] ) ) ) {
506
  $tmp_file = sanitize_text_field( $_FILES['async-upload']['tmp_name'] );
507
  $raw_data = file_get_contents( $tmp_file );
555
  );
556
 
557
  if ( ! empty( $users ) ) {
558
+ $raw_data = '';
559
  $seperator = ';';
560
  $data_contain_headers = false;
561
+
562
  $headers = array(
563
  __( 'Email', 'email-subscribers' ),
564
  __( 'First Name', 'email-subscribers' ),
566
  __( 'Nick Name', 'email-subscribers' ),
567
  __( 'Display Name', 'email-subscribers' ),
568
  );
569
+
570
  foreach ( $users as $user ) {
571
+
572
  // User must have a role assigned.
573
  if ( ! $user->_role ) {
574
  continue;
575
  }
576
+
577
  // Role is set but not in the list
578
  if ( ! empty( $roles ) && ! array_intersect( array_keys( unserialize( $user->_role ) ), $roles ) ) {
579
  continue;
580
  }
581
+
582
  $user_data = array();
583
+
584
  foreach ( $user as $key => $data ) {
585
  if ( '_role' === $key ) {
586
  continue;
587
  }
588
+
589
  if ( 'firstname' === $key && ! $data ) {
590
  $data = $user->display_name;
591
  }
592
+
593
  $user_data[] = $data;
594
  }
595
+
596
  $raw_data .= implode( ';', $user_data );
597
  $raw_data .= "\n";
598
  }
605
  if ( empty( $raw_data ) ) {
606
  wp_send_json( $response );
607
  }
608
+
609
+ $response = self::insert_into_temp_table( $raw_data, $seperator, $data_contain_headers, $headers, '', $importing_from );
610
  $response['success'] = true;
611
  $response['memoryusage'] = size_format( memory_get_peak_usage( true ), 2 );
612
+
613
  wp_send_json( $response );
614
  }
615
 
616
  /**
617
  * Ajax handler to get import data from temporary table.
618
+ *
619
  * @since 4.6.6
620
  */
621
  public function ajax_get_import_data() {
630
 
631
  $identifier = '';
632
  if ( isset( $_POST['identifier'] ) ) {
633
+ $identifier = sanitize_text_field( $_POST['identifier'] );
634
  }
635
 
636
  if ( ! empty( $identifier ) ) {
637
+
638
  $response['identifier'] = $identifier;
639
+ $response['data'] = get_option( 'ig_es_bulk_import' );
640
  // get first and last entry
641
  $entries = $wpdb->get_row(
642
  $wpdb->prepare(
653
  $data = str_getcsv( $first[0], $response['data']['separator'], '"' );
654
  $cols = count( $data );
655
  $contactcount = $response['data']['lines'];
656
+ $fields = array(
657
  'email' => __( 'Email', 'email-subscribers' ),
658
  'first_name' => __( 'First Name', 'email-subscribers' ),
659
  'last_name' => __( 'Last Name', 'email-subscribers' ),
661
  'last_first' => __( '(Last Name) (First Name)', 'email-subscribers' ),
662
  'created_at' => __( 'Subscribed at', 'email-subscribers' ),
663
  );
664
+ if ( ! empty( $response['data']['importing_from'] ) && 'wordpress_users' !== $response['data']['importing_from'] ) {
665
  $fields['list_name'] = __( 'List Name', 'email-subscribers' );
666
  $fields['status'] = __( 'Status', 'email-subscribers' );
667
  }
680
 
681
  </label>
682
  </div>
683
+ </div>';
684
  $html .= '<div class="w-3/4 mx-4 border-b border-gray-200 shadow rounded-lg"><table class="w-full bg-white rounded-lg shadow overflow-hidden ">';
685
  $html .= '<thead><tr class="border-b border-gray-200 bg-gray-50 text-left text-sm leading-4 font-medium text-gray-500 tracking-wider"><th class="pl-3 py-4" style="width:20px;">#</th>';
686
  $phpmailer = ES()->mailer->get_phpmailer();
703
  $is_selected = true;
704
  } elseif ( ! empty( $headers[ $i ] ) ) {
705
  if ( strip_tags( $headers[ $i ] ) === $fields[ $key ] ) {
706
+ $is_selected = ( 'first_name' === $key ) || ( 'last_name' === $key ) || ( 'list_name' === $key && 'mailchimp-api' === $response['data']['importing_from'] ) || ( 'status' === $key && 'mailchimp-api' === $response['data']['importing_from'] );
707
  }
708
  }
709
+ $select .= '<option value="' . $key . '" ' . ( $is_selected ? 'selected' : '' ) . '>' . $value . '</option>';
710
  }
711
  $select .= '</select>';
712
  $html .= '<th class="pl-3 py-4 font-medium">' . $select . '</th>';
721
  }
722
  $html .= '</thead><tbody>';
723
  for ( $i = 0; $i < min( 3, $contactcount ); $i++ ) {
724
+ $data = str_getcsv( ( $first[ $i ] ), $response['data']['separator'], '"' );
725
  $html .= '<tr class="border-b border-gray-200 text-left text-sm leading-4 text-gray-500 tracking-wide"><td class="pl-3">' . number_format_i18n( $i + 1 ) . '</td>';
726
  foreach ( $data as $cell ) {
727
  if ( ! empty( $cell ) && is_email( $cell ) ) {
752
  $html .= '</div></div>';
753
 
754
  $response['html'] = $html;
755
+ $response['success'] = true;
756
  }
757
 
758
  wp_send_json( $response );
760
 
761
  /**
762
  * Ajax handler to import subscirbers from temporary table
763
+ *
764
  * @since 4.6.6
765
  */
766
  public function ajax_do_import() {
796
  if ( isset( $_POST['options'] ) ) {
797
  $bulkdata = ig_es_get_data( $_POST, 'options', array() );
798
  }
799
+
800
+ $bulkdata = wp_parse_args( $bulkdata, get_option( 'ig_es_bulk_import' ) );
801
+ $erroremails = get_option( 'ig_es_bulk_import_errors', array() );
802
+ $order = isset( $bulkdata['mapping_order'] ) ? $bulkdata['mapping_order'] : array();
803
+ $list_id = isset( $bulkdata['list_id'] ) ? $bulkdata['list_id'] : array();
804
+ $parts_at_once = 10;
805
  $selected_status = $bulkdata['status'];
806
+
807
  $error_codes = array(
808
+ 'invalid' => __( 'Email address is invalid.', 'email-subscribers' ),
809
+ 'empty' => __( 'Email address is empty.', 'email-subscribers' ),
810
  );
811
 
812
  if ( ! empty( $list_id ) && ! is_array( $list_id ) ) {
816
  if ( isset( $_POST['id'] ) ) {
817
 
818
  $bulkdata['current'] = (int) sanitize_text_field( $_POST['id'] );
819
+ $raw_list_data = $wpdb->get_col(
820
  $wpdb->prepare(
821
  "SELECT data FROM {$wpdb->prefix}ig_temp_import
822
  WHERE identifier = %s ORDER BY ID ASC LIMIT %d, %d",
834
  $processed_emails = ! empty( $bulkdata['processed_emails'] ) ? $bulkdata['processed_emails'] : array();
835
  $list_contact_data = array();
836
  $es_status_mapping = array(
837
+ __( 'Subscribed', 'email-subscribers' ) => 'subscribed',
838
+ __( 'Unsubscribed', 'email-subscribers' ) => 'unsubscribed',
839
+ __( 'Unconfirmed', 'email-subscribers' ) => 'unconfirmed',
840
+ __( 'Hard Bounced', 'email-subscribers' ) => 'hard_bounced',
841
  );
842
+
843
  foreach ( $raw_list_data as $raw_list ) {
844
  $raw_list = unserialize( base64_decode( $raw_list ) );
845
  // each entry
858
  }
859
  switch ( $order[ $col ] ) {
860
  case 'email':
861
+ $insert['email'] = $d;
862
  // Convert special characters in the email domain name to ascii.
863
  if ( is_callable( array( $phpmailer, 'punyencodeAddress' ) ) ) {
864
  $encoded_email = $phpmailer->punyencodeAddress( $insert['email'] );
865
  if ( ! empty( $encoded_email ) ) {
866
+ $insert['email'] = $encoded_email;
867
  }
868
  }
869
  break;
873
  $insert['first_name'] = $name[0];
874
  }
875
  if ( ! empty( $name[1] ) ) {
876
+ $insert['last_name'] = $name[1];
877
  }
878
  break;
879
  case 'last_first':
882
  $insert['first_name'] = $name[1];
883
  }
884
  if ( ! empty( $name[0] ) ) {
885
+ $insert['last_name'] = $name[0];
886
  }
887
  break;
888
  case 'created_at':
889
  if ( ! is_numeric( $d ) && ! empty( $d ) ) {
890
+ $d = sanitize_text_field( $d );
891
  $insert['created_at'] = gmdate( 'Y-m-d H:i:s', strtotime( $d ) - $gmt_offset );
892
  }
893
  break;
898
  $insert[ $order[ $col ] ] = $d;
899
  }
900
  }
901
+
902
  if ( empty( $insert['email'] ) || ! is_email( $insert['email'] ) ) {
903
  $error_data = array();
904
  if ( empty( $insert['email'] ) ) {
926
 
927
  $guid = ES_Common::generate_guid();
928
 
929
+ $contacts_data[ $email ]['first_name'] = $first_name;
930
+ $contacts_data[ $email ]['last_name'] = $last_name;
931
+ $contacts_data[ $email ]['email'] = $email;
932
+ $contacts_data[ $email ]['source'] = 'import';
933
+ $contacts_data[ $email ]['status'] = 'verified';
934
+ $contacts_data[ $email ]['hash'] = $guid;
935
+ $contacts_data[ $email ]['created_at'] = $created_at;
936
 
937
  $bulkdata['imported']++;
938
  } else {
942
  $list_names = isset( $insert['list_name'] ) ? sanitize_text_field( trim( $insert['list_name'] ) ) : '';
943
  if ( empty( $insert['list_name'] ) ) {
944
  $list_names_arr = ES()->lists_db->get_lists_by_id( $list_id );
945
+ $list_names = implode( ',', array_column( $list_names_arr, 'name' ) );
946
  }
947
 
948
  $status = 'unconfirmed';
949
+ $list_names = array_map( 'trim', explode( ',', $list_names ) );
950
 
 
951
  if ( isset( $insert['status'] ) ) {
952
  $map_status = strtolower( str_replace( ' ', '_', $insert['status'] ) );
953
  }
954
+
955
+ if ( isset( $insert['status'] ) && in_array( $map_status, $es_status_mapping ) ) {
956
  $status = sanitize_text_field( trim( $map_status ) );
957
  } elseif ( ! empty( $selected_status ) ) {
958
  $status = $selected_status;
959
+ }
960
 
961
  if ( ! empty( $es_status_mapping[ $status ] ) ) {
962
  $status = $es_status_mapping[ $status ];
964
 
965
  foreach ( $list_names as $key => $list_name ) {
966
  if ( ! empty( $list_name ) ) {
967
+ $list_contact_data[ $list_name ][ $status ][] = $email;
968
  }
969
  }
970
 
971
  $current_batch_emails[] = $email;
972
  }
973
  }
974
+
975
  if ( count( $current_batch_emails ) > 0 ) {
976
 
977
  $current_batch_emails = array_unique( $current_batch_emails );
978
 
979
  $existing_contacts_email_id_map = ES()->contacts_db->get_email_id_map( $current_batch_emails );
980
  if ( ! empty( $existing_contacts_email_id_map ) ) {
981
+ $contacts_data = array_diff_key( $contacts_data, $existing_contacts_email_id_map );
982
  }
983
 
984
  if ( ! empty( $contacts_data ) ) {
986
  }
987
 
988
  if ( ! empty( $list_contact_data ) ) {
989
+ foreach ( $list_contact_data as $list_name => $list_data ) {
990
  $list = ES()->lists_db->get_list_by_name( $list_name );
991
+
992
  if ( ! empty( $list ) ) {
993
  $list_id = $list['id'];
994
  } else {
995
  $list_id = ES()->lists_db->add_list( $list_name );
996
  }
997
 
998
+ foreach ( $list_data as $status => $contact_emails ) {
999
  $contact_id_date = ES()->contacts_db->get_contact_ids_created_at_date_by_emails( $contact_emails );
1000
+ $contact_ids = array_keys( $contact_id_date );
1001
  if ( count( $contact_ids ) > 0 ) {
1002
  ES()->lists_contacts_db->remove_contacts_from_lists( $contact_ids, $list_id );
1003
  ES()->lists_contacts_db->do_import_contacts_into_list( $list_id, $contact_id_date, $status, 1 );
1004
  }
1005
  }
1006
  }
1007
+ }
1008
  }
1009
  }
1010
 
1011
  $return['memoryusage'] = size_format( memory_get_peak_usage( true ), 2 );
1012
+ $return['errors'] = isset( $bulkdata['errors'] ) ? $bulkdata['errors'] : 0;
1013
+ $return['duplicate_emails_count'] = isset( $bulkdata['duplicate_emails_count'] ) ? $bulkdata['duplicate_emails_count'] : 0;
1014
  $return['imported'] = ( $bulkdata['imported'] );
1015
  $return['total'] = ( $bulkdata['lines'] );
1016
  $return['f_errors'] = number_format_i18n( $bulkdata['errors'] );
1025
  $return['html'] .= '<p class="text-base text-gray-600 pt-2 pb-1.5">' . sprintf( esc_html__( '%1$s of %2$s contacts imported.', 'email-subscribers' ), '<span class="font-medium">' . number_format_i18n( $bulkdata['imported'] ) . '</span>', '<span class="font-medium">' . number_format_i18n( $bulkdata['lines'] ) . '</span>' );
1026
 
1027
  if ( $bulkdata['duplicate_emails_count'] ) {
1028
+ $duplicate_email_string = _n( 'email', 'emails', $bulkdata['duplicate_emails_count'], 'email-subscribers' );
1029
  /* translators: 1. Duplicate emails count. 2. Email or emails string based on duplicate email count. */
1030
  $return['html'] .= sprintf( esc_html__( '%1$s duplicate %2$s found.', 'email-subscribers' ), '<span class="font-medium">' . number_format_i18n( $bulkdata['duplicate_emails_count'] ) . '</span>', $duplicate_email_string );
1031
  }
1032
  $return['html'] .= '</p>';
1033
  if ( $bulkdata['errors'] ) {
1034
+ $i = 0;
1035
  $skipped_contact_string = _n( 'contact was', 'contacts were', $bulkdata['errors'], 'email-subscribers' );
1036
+
1037
  /* translators: %d Skipped emails count %s Skipped contacts string */
1038
  $table = '<p class="text-sm text-gray-600 pt-2 pb-1.5">' . __( sprintf( 'The following %d %s skipped', $bulkdata['errors'], $skipped_contact_string ), 'email-subscribers' ) . ':</p>';
1039
  $table .= '<table class="w-full bg-white rounded-lg shadow overflow-hidden mt-1.5">';
1048
  if ( $last_name_column_choosen ) {
1049
  $table .= '<th class="pl-3 py-3 font-medium">' . esc_html__( 'Last Name', 'email-subscribers' ) . '</th>';
1050
  }
1051
+
1052
  $table .= '<th class="pl-3 py-3 font-medium">' . esc_html__( 'Email', 'email-subscribers' ) . '</th>';
1053
  $table .= '<th class="pl-3 pr-1 py-3 font-medium">' . esc_html__( 'Reason', 'email-subscribers' ) . '</th>';
1054
  $table .= '</tr></thead><tbody>';
1065
  $table .= '<td class="pl-3 py-3">' . esc_html( $last_name ) . '</td>';
1066
  }
1067
  $error_code = ! empty( $error_data['cd'] ) ? $error_data['cd'] : '-';
1068
+ $reason = ! empty( $error_codes[ $error_code ] ) ? $error_codes[ $error_code ] : '-';
1069
  $table .= '<td class="pl-3 py-3">' . esc_html( $email ) . '</td><td class="pl-3 py-3">' . esc_html( $reason ) . '</td></tr>';
1070
  }
1071
  $table .= '</tbody></table>';
1074
  do_action( 'ig_es_remove_import_data' );
1075
  } else {
1076
  // Add current batch emails into the processed email list
1077
+ $processed_emails = array_merge( $processed_emails, $current_batch_emails );
1078
  $bulkdata['processed_emails'] = $processed_emails;
1079
 
1080
  update_option( 'ig_es_bulk_import', $bulkdata );
1088
 
1089
  /**
1090
  * Method to truncate temp import table and options used during import process
1091
+ *
1092
  * @param string import identifier
1093
+ *
1094
  * @since 4.6.6
1095
+ *
1096
  * @since 4.7.5 Renamed the function, converted to static method
1097
  */
1098
  public static function remove_import_data( $identifier = '' ) {
1105
  delete_option( 'ig_es_bulk_import' );
1106
  delete_option( 'ig_es_bulk_import_errors' );
1107
 
1108
+ // We are trancating table so that primary key is reset to 1 otherwise ID column's value will increase on every insert and at some point ID column's data type may not be able to accomodate its value resulting in insert to fail.
1109
  $wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}ig_temp_import" );
1110
  }
1111
 
 
1112
  }
1113
 
1114
  public function api() {
1115
 
1116
+ $mailchimp_apikey = ig_es_get_request_data( 'mailchimp_api_key' );
1117
  if ( ! $this->api ) {
1118
  $this->api = new ES_Mailchimp_API( $mailchimp_apikey );
1119
  }
1136
  );
1137
  break;
1138
  case 'import_list':
1139
+ $limit = ig_es_get_request_data( 'limit' );
1140
+ $offset = ig_es_get_request_data( 'offset' );
1141
+ $contact_status = ig_es_get_request_data( 'status' );
1142
+ $import_identifier = ig_es_get_request_data( 'identifier' );
1143
+
1144
  if ( ! isset( $_POST['id'] ) ) {
1145
  wp_send_json_error(
1146
  array(
1149
  );
1150
  }
1151
 
1152
+ $limit = isset( $limit ) ? (int) $limit : 1000;
1153
+ $offset = isset( $offset ) ? (int) $offset : 0;
1154
+ $status = isset( $contact_status ) ? (array) $contact_status : array( 'subscribed' );
1155
  $identifier = isset( $import_identifier ) ? $import_identifier : '';
1156
+ $list_id = ig_es_get_request_data( 'id' );
1157
 
1158
  $subscribers = $this->api()->members(
1159
  $list_id,
1164
  )
1165
  );
1166
 
1167
+ $list_name = ig_es_get_request_data( 'list_name' );
1168
 
1169
  $importing_from = 'mailchimp-api';
1170
  $raw_data = '';
1180
  );
1181
 
1182
  $es_mailchimp_status_mapping = array(
1183
+ 'subscribed' => __( 'Subscribed', 'email-subscribers' ),
1184
+ 'unsubscribed' => __( 'Unsubscribed', 'email-subscribers' ),
1185
+ 'pending' => __( 'Unconfirmed', 'email-subscribers' ),
1186
+ 'cleaned' => __( 'Hard Bounced', 'email-subscribers' ),
1187
  );
1188
  foreach ( $subscribers as $subscriber ) {
1189
  if ( ! $subscriber->email_address ) {
1192
  $user_data = array();
1193
 
1194
  $list_name = ! empty( $list_name ) ? $list_name : 'Test';
1195
+ $status = ! empty( $subscriber->status ) ? $subscriber->status : 'subscribed';
1196
  if ( ! empty( $es_mailchimp_status_mapping[ $status ] ) ) {
1197
  $status = $es_mailchimp_status_mapping[ $status ];
1198
  }
1211
  $response = array();
1212
 
1213
  if ( ! empty( $raw_data ) ) {
1214
+ $result = self::insert_into_temp_table( $raw_data, $seperator, $data_contain_headers, $headers, $identifier, 'mailchimp-api' );
1215
  $identifier = $result['identifier'];
1216
  }
1217
  $response = array(
1220
  'subscribers' => count( $subscribers ),
1221
  'identifier' => $identifier,
1222
  );
1223
+
1224
  wp_send_json_success( $response );
1225
  break;
1226
  case 'verify_api_key':
1244
  global $wpdb;
1245
  $raw_data = ( trim( str_replace( array( "\r", "\r\n", "\n\n" ), "\n", $raw_data ) ) );
1246
 
 
1247
  if ( function_exists( 'mb_convert_encoding' ) ) {
1248
  $encoding = mb_detect_encoding( $raw_data, 'auto' );
1249
  } else {
1250
  $encoding = 'UTF-8';
1251
  }
1252
+
1253
  $lines = explode( "\n", $raw_data );
1254
 
1255
  // If data itself contains headers(in case of CSV), then remove it.
1256
  if ( $data_contain_headers ) {
1257
  array_shift( $lines );
1258
  }
1259
+
1260
  $lines_count = count( $lines );
1261
+
1262
  $batch_size = min( 500, max( 200, round( count( $lines ) / 200 ) ) ); // Each entry in temporary import table will have this much of subscribers data
1263
  $parts = array_chunk( $lines, $batch_size );
1264
  $partcount = count( $parts );
1265
 
1266
  do_action( 'ig_es_remove_import_data', $identifier );
1267
 
1268
+ $identifier = empty( $identifier ) ? uniqid() : $identifier;
1269
  $response['identifier'] = $identifier;
1270
 
1271
  for ( $i = 0; $i < $partcount; $i++ ) {
1272
 
1273
  $part = $parts[ $i ];
1274
+
1275
  $new_value = base64_encode( serialize( $part ) );
1276
 
1277
  $wpdb->query( $wpdb->prepare( "INSERT INTO {$wpdb->prefix}ig_temp_import (data, identifier) VALUES (%s, %s)", $new_value, $identifier ) );
1279
 
1280
  $bulk_import_data = get_option( 'ig_es_bulk_import', array() );
1281
  if ( ! empty( $bulk_import_data ) ) {
1282
+ $partcount += $bulk_import_data['parts'];
1283
  $lines_count += $bulk_import_data['lines'];
1284
  }
1285
+
1286
  $bulkimport = array(
1287
  'imported' => 0,
1288
  'errors' => 0,
1293
  'separator' => $seperator,
1294
  'importing_from' => $importing_from,
1295
  'data_contain_headers' => $data_contain_headers,
1296
+ 'headers' => $headers,
1297
  );
1298
 
1299
  $response['success'] = true;
lite/includes/classes/class-es-info.php CHANGED
@@ -19,7 +19,7 @@ class ES_Info {
19
  $help_title = __( 'Help & Info', 'email-subscribers' );
20
  add_submenu_page( 'es_dashboard', $help_title, $help_title, 'edit_posts', 'es_general_information', array( $this, 'es_information_callback' ) );
21
 
22
- $pro_title = '<span class="es-fire-sale"> 🔥 </span>' . esc_html__( ' Go Pro', 'email-subscribers' );
23
  if ( ! ES()->is_pro() ) {
24
  add_submenu_page( 'es_dashboard', $pro_title, $pro_title, 'edit_posts', 'es_pricing', array( $this, 'es_pricing_callback' ) );
25
  }
19
  $help_title = __( 'Help & Info', 'email-subscribers' );
20
  add_submenu_page( 'es_dashboard', $help_title, $help_title, 'edit_posts', 'es_general_information', array( $this, 'es_information_callback' ) );
21
 
22
+ $pro_title = '<span class="es-fire-sale"> 🔥 </span>' . esc_html__( ' Go Pro', 'email-subscribers' );
23
  if ( ! ES()->is_pro() ) {
24
  add_submenu_page( 'es_dashboard', $pro_title, $pro_title, 'edit_posts', 'es_pricing', array( $this, 'es_pricing_callback' ) );
25
  }
lite/includes/classes/class-es-list-table.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
 
3
  if ( ! class_exists( 'WP_List_Table' ) ) {
4
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
5
  }
6
 
7
  class ES_List_Table extends WP_List_Table {
@@ -11,7 +11,6 @@ class ES_List_Table extends WP_List_Table {
11
  *
12
  * @since 4.6.6
13
  * @var int
14
- *
15
  */
16
  public $per_page = 10;
17
 
@@ -31,15 +30,17 @@ class ES_List_Table extends WP_List_Table {
31
  $this->search_box( $search_str, 'form-search-input' );
32
 
33
  $per_page = $this->get_items_per_page( static::$option_per_page, 25 );
34
- //$per_page = $this->per_page; // Show Max 10 records per page
35
 
36
  $current_page = $this->get_pagenum();
37
  $total_items = $this->get_lists( 0, 0, true );
38
 
39
- $this->set_pagination_args( array(
40
- 'total_items' => $total_items, //WE have to calculate the total number of items
41
- 'per_page' => $per_page //WE have to determine how many items to show on a page
42
- ) );
 
 
43
 
44
  $this->items = $this->get_lists( $per_page, $current_page );
45
  }
@@ -47,8 +48,8 @@ class ES_List_Table extends WP_List_Table {
47
  /**
48
  * Get Lists
49
  *
50
- * @param int $per_page
51
- * @param int $current_page
52
  * @param false $do_count_only
53
  *
54
  * @since 4.6.6
@@ -96,13 +97,12 @@ class ES_List_Table extends WP_List_Table {
96
  * Add Row action
97
  *
98
  * @param string[] $actions
99
- * @param bool $always_visible
100
- * @param string $class
101
  *
102
  * @return string
103
  *
104
  * @since 4.6.6
105
- *
106
  */
107
  protected function row_actions( $actions, $always_visible = false, $class = '' ) {
108
  $action_count = count( $actions );
@@ -116,7 +116,7 @@ class ES_List_Table extends WP_List_Table {
116
  foreach ( $actions as $action => $link ) {
117
  ++ $i;
118
  ( $i == $action_count ) ? $sep = '' : $sep = ' | ';
119
- $out .= "<span class='$action'>$link$sep</span>";
120
  }
121
  $out .= '</div>';
122
 
1
  <?php
2
 
3
  if ( ! class_exists( 'WP_List_Table' ) ) {
4
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
5
  }
6
 
7
  class ES_List_Table extends WP_List_Table {
11
  *
12
  * @since 4.6.6
13
  * @var int
 
14
  */
15
  public $per_page = 10;
16
 
30
  $this->search_box( $search_str, 'form-search-input' );
31
 
32
  $per_page = $this->get_items_per_page( static::$option_per_page, 25 );
33
+ // $per_page = $this->per_page; // Show Max 10 records per page
34
 
35
  $current_page = $this->get_pagenum();
36
  $total_items = $this->get_lists( 0, 0, true );
37
 
38
+ $this->set_pagination_args(
39
+ array(
40
+ 'total_items' => $total_items, // WE have to calculate the total number of items
41
+ 'per_page' => $per_page, // WE have to determine how many items to show on a page
42
+ )
43
+ );
44
 
45
  $this->items = $this->get_lists( $per_page, $current_page );
46
  }
48
  /**
49
  * Get Lists
50
  *
51
+ * @param int $per_page
52
+ * @param int $current_page
53
  * @param false $do_count_only
54
  *
55
  * @since 4.6.6
97
  * Add Row action
98
  *
99
  * @param string[] $actions
100
+ * @param bool $always_visible
101
+ * @param string $class
102
  *
103
  * @return string
104
  *
105
  * @since 4.6.6
 
106
  */
107
  protected function row_actions( $actions, $always_visible = false, $class = '' ) {
108
  $action_count = count( $actions );
116
  foreach ( $actions as $action => $link ) {
117
  ++ $i;
118
  ( $i == $action_count ) ? $sep = '' : $sep = ' | ';
119
+ $out .= "<span class='$action'>$link$sep</span>";
120
  }
121
  $out .= '</div>';
122
 
lite/includes/classes/class-es-lists-table.php CHANGED
@@ -64,13 +64,13 @@ class ES_Lists_Table extends ES_List_Table {
64
 
65
  ?>
66
  <div class="wrap pt-4 font-sans">
67
- <?php
68
  if ( 'new' === $action ) {
69
  $this->es_new_lists_callback();
70
  } elseif ( 'edit' === $action ) {
71
  $list = ig_es_get_request_data( 'list' );
72
  echo wp_kses_post( $this->edit_list( absint( $list ) ) );
73
- } else {
74
  ?>
75
 
76
  <div class="max-w-full -mt-3 font-sans">
@@ -88,7 +88,7 @@ class ES_Lists_Table extends ES_List_Table {
88
  <h2 class="-mt-1.5 text-2xl font-medium text-gray-700 sm:leading-7 sm:truncate"> <?php esc_html_e( 'Lists', 'email-subscribers' ); ?>
89
  </h2>
90
  </div>
91
- <div class="mt-4"> <a href="admin.php?page=es_lists&action=new" class="ig-es-title-button ml-2"><?php esc_html_e('Add New', 'email-subscribers'); ?></a>
92
  </div>
93
  </div>
94
  </header>
@@ -116,7 +116,7 @@ class ES_Lists_Table extends ES_List_Table {
116
  <br class="clear">
117
  </div>
118
  </div>
119
- <?php
120
  }
121
  }
122
 
@@ -233,7 +233,7 @@ class ES_Lists_Table extends ES_List_Table {
233
  if ( $save ) {
234
  $message = __( 'List updated successfully!', 'email-subscribers' );
235
  ES_Common::show_message( $message, 'success' );
236
- }
237
  } else {
238
 
239
  $id = $list['id'];
@@ -276,7 +276,7 @@ class ES_Lists_Table extends ES_List_Table {
276
  <a class="hover:underline " href="admin.php?page=es_subscribers"><?php esc_html_e( 'Audience ', 'email-subscribers' ); ?></a>
277
  <svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
278
 
279
- <a class="hover:underline" href="admin.php?page=es_lists&action=manage-lists"><?php esc_html_e(' Lists ', 'email-subscribers'); ?></a>
280
  <svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
281
  </li>
282
  </ol>
@@ -319,7 +319,7 @@ class ES_Lists_Table extends ES_List_Table {
319
  </div>
320
 
321
  <?php
322
-
323
  $submit_button_text = $is_new ? __( 'Save List', 'email-subscribers' ) : __( 'Save Changes', 'email-subscribers' );
324
  ?>
325
  <input type="hidden" name="submitted" value="submitted"/>
@@ -382,7 +382,7 @@ class ES_Lists_Table extends ES_List_Table {
382
  $sql = 'SELECT * FROM ' . IG_LISTS_TABLE;
383
  }
384
 
385
- $args = array();
386
  $query = array();
387
 
388
  $add_where_clause = false;
@@ -563,7 +563,7 @@ class ES_Lists_Table extends ES_List_Table {
563
 
564
  $allowedtags = ig_es_allowed_html_tags_in_esc();
565
  $tooltip_html = ES_Common::get_tooltip_html( __( 'Unique hash key that can be used to subscribe users to the list from external sites.', 'email-subscribers' ) );
566
-
567
  $columns = array(
568
  'cb' => '<input type="checkbox" />',
569
  'name' => __( 'Name', 'email-subscribers' ),
@@ -624,7 +624,7 @@ class ES_Lists_Table extends ES_List_Table {
624
  <input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>"/>
625
  <?php submit_button( __( 'Search lists', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
626
  </p>
627
- <?php
628
  }
629
 
630
  /**
64
 
65
  ?>
66
  <div class="wrap pt-4 font-sans">
67
+ <?php
68
  if ( 'new' === $action ) {
69
  $this->es_new_lists_callback();
70
  } elseif ( 'edit' === $action ) {
71
  $list = ig_es_get_request_data( 'list' );
72
  echo wp_kses_post( $this->edit_list( absint( $list ) ) );
73
+ } else {
74
  ?>
75
 
76
  <div class="max-w-full -mt-3 font-sans">
88
  <h2 class="-mt-1.5 text-2xl font-medium text-gray-700 sm:leading-7 sm:truncate"> <?php esc_html_e( 'Lists', 'email-subscribers' ); ?>
89
  </h2>
90
  </div>
91
+ <div class="mt-4"> <a href="admin.php?page=es_lists&action=new" class="ig-es-title-button ml-2"><?php esc_html_e( 'Add New', 'email-subscribers' ); ?></a>
92
  </div>
93
  </div>
94
  </header>
116
  <br class="clear">
117
  </div>
118
  </div>
119
+ <?php
120
  }
121
  }
122
 
233
  if ( $save ) {
234
  $message = __( 'List updated successfully!', 'email-subscribers' );
235
  ES_Common::show_message( $message, 'success' );
236
+ }
237
  } else {
238
 
239
  $id = $list['id'];
276
  <a class="hover:underline " href="admin.php?page=es_subscribers"><?php esc_html_e( 'Audience ', 'email-subscribers' ); ?></a>
277
  <svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
278
 
279
+ <a class="hover:underline" href="admin.php?page=es_lists&action=manage-lists"><?php esc_html_e( ' Lists ', 'email-subscribers' ); ?></a>
280
  <svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
281
  </li>
282
  </ol>
319
  </div>
320
 
321
  <?php
322
+
323
  $submit_button_text = $is_new ? __( 'Save List', 'email-subscribers' ) : __( 'Save Changes', 'email-subscribers' );
324
  ?>
325
  <input type="hidden" name="submitted" value="submitted"/>
382
  $sql = 'SELECT * FROM ' . IG_LISTS_TABLE;
383
  }
384
 
385
+ $args = array();
386
  $query = array();
387
 
388
  $add_where_clause = false;
563
 
564
  $allowedtags = ig_es_allowed_html_tags_in_esc();
565
  $tooltip_html = ES_Common::get_tooltip_html( __( 'Unique hash key that can be used to subscribe users to the list from external sites.', 'email-subscribers' ) );
566
+
567
  $columns = array(
568
  'cb' => '<input type="checkbox" />',
569
  'name' => __( 'Name', 'email-subscribers' ),
624
  <input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>"/>
625
  <?php submit_button( __( 'Search lists', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
626
  </p>
627
+ <?php
628
  }
629
 
630
  /**
lite/includes/classes/class-es-mailchimp-api.php CHANGED
@@ -32,7 +32,7 @@ class ES_Mailchimp_API {
32
 
33
  /**
34
  * Get total items
35
- *
36
  * @since 4.6.14
37
  */
38
  public function get_total_items() {
@@ -41,7 +41,7 @@ class ES_Mailchimp_API {
41
 
42
  /**
43
  * Verify API Key
44
- *
45
  * @since 4.6.14
46
  */
47
  public function ping() {
@@ -50,7 +50,7 @@ class ES_Mailchimp_API {
50
 
51
  /**
52
  * Get list of audience lists
53
- *
54
  * @since 4.6.14
55
  */
56
  public function lists( $args = array() ) {
@@ -60,7 +60,7 @@ class ES_Mailchimp_API {
60
 
61
  /**
62
  * Get specific audience list
63
- *
64
  * @since 4.6.14
65
  */
66
  public function get_list( $list_id, $args = array() ) {
@@ -71,7 +71,7 @@ class ES_Mailchimp_API {
71
  * Get contacts from specific list
72
  *
73
  * @param list_id
74
- *
75
  * @since 4.6.14
76
  */
77
  public function members( $list_id, $args = array() ) {
@@ -89,7 +89,7 @@ class ES_Mailchimp_API {
89
 
90
  /**
91
  * Get data from Mailchimp API (Lists, contacts)
92
- *
93
  * @since 4.6.14
94
  */
95
  private function do_call( $method, $action, $args = array(), $timeout = 15 ) {
32
 
33
  /**
34
  * Get total items
35
+ *
36
  * @since 4.6.14
37
  */
38
  public function get_total_items() {
41
 
42
  /**
43
  * Verify API Key
44
+ *
45
  * @since 4.6.14
46
  */
47
  public function ping() {
50
 
51
  /**
52
  * Get list of audience lists
53
+ *
54
  * @since 4.6.14
55
  */
56
  public function lists( $args = array() ) {
60
 
61
  /**
62
  * Get specific audience list
63
+ *
64
  * @since 4.6.14
65
  */
66
  public function get_list( $list_id, $args = array() ) {
71
  * Get contacts from specific list
72
  *
73
  * @param list_id
74
+ *
75
  * @since 4.6.14
76
  */
77
  public function members( $list_id, $args = array() ) {
89
 
90
  /**
91
  * Get data from Mailchimp API (Lists, contacts)
92
+ *
93
  * @since 4.6.14
94
  */
95
  private function do_call( $method, $action, $args = array(), $timeout = 15 ) {
lite/includes/classes/class-es-mailer.php CHANGED
@@ -146,7 +146,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
146
 
147
  // Add filter to increase memory limit
148
  add_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' );
149
-
150
  wp_raise_memory_limit( 'ig_es' );
151
 
152
  // Remove the added filter function so that it won't be called again if wp_raise_memory_limit called later on.
@@ -162,10 +162,9 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
162
 
163
  /**
164
  * Check if memory limit is exceeded
165
- *
166
  * For mailers supporting batch APIs, since we need to prepare and store subscriber's email data before dispatching it
167
  * memory limit can be reached in that case.
168
- *
169
  */
170
  if ( IG_ES_Background_Process_Helper::memory_exceeded() ) {
171
  return true;
@@ -199,7 +198,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
199
 
200
  $subject = $this->get_admin_new_contact_email_subject();
201
  $subject = $this->replace_admin_notification_merge_tags( $data, $subject );
202
-
203
  $content = $this->get_admin_new_contact_email_content();
204
  $content = $this->replace_admin_notification_merge_tags( $data, $content );
205
 
@@ -336,9 +335,9 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
336
 
337
  $email_count = $notification['count'];
338
  $post_subject = $notification['subject'];
339
- $cron_date = gmdate( 'Y-m-d H:i:s' );
340
  $cron_local_date = get_date_from_gmt( $cron_date ); // Convert from GMT to local date/time based on WordPress time zone setting.
341
- $cron_date = ES_Common::convert_date_to_wp_date( $cron_local_date ); // Get formatted date from WordPress date/time settings.
342
 
343
  $content = str_replace( '{{DATE}}', $cron_date, $content );
344
  $content = str_replace( '{{COUNT}}', $email_count, $content );
@@ -590,9 +589,9 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
590
  if ( ! empty( $campaign ) ) {
591
  $campaign_type = $campaign['type'];
592
  if ( 'newsletter' === $campaign_type ) {
593
- $from_name = ! empty( $campaign['from_name'] ) ? $campaign['from_name'] : '';
594
- $from_email = ! empty( $campaign['from_email'] ) ? $campaign['from_email'] : '';
595
- $reply_to_email = ! empty( $campaign['reply_to_email'] ) ? $campaign['reply_to_email']: '';
596
  $sender_data['from_name'] = $from_name;
597
  $sender_data['from_email'] = $from_email;
598
  $sender_data['reply_to_email'] = $reply_to_email;
@@ -649,16 +648,15 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
649
  $this->email_id_map = ES_DB_Sending_Queue::get_emails_id_map_by_campaign( $campaign_id, $emails );
650
  }
651
  }
652
-
653
 
654
  $total_emails_to_send = count( $emails );
655
-
656
  // In case mailser supporting batch APIs, we are setting API credentials, sender data before running the email loop
657
  // For normal mailers, we are doing this inside the loop
658
  if ( $total_emails_to_send > 1 && $this->mailer->support_batch_sending ) {
659
-
660
  $mailer_data_set = $this->mailer->set_mailer_data();
661
-
662
  // Error setting up mailer?
663
  if ( is_wp_error( $mailer_data_set ) ) {
664
  $response['status'] = 'ERROR';
@@ -694,7 +692,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
694
  } elseif ( empty( $reply_to_email ) ) {
695
  $reply_to_email = $this->get_from_email();
696
  }
697
-
698
  $charset = get_bloginfo( 'charset' );
699
  $subject = html_entity_decode( $subject, ENT_QUOTES, $charset );
700
  $content = preg_replace( '/data-json=".*?"/is', '', $content );
@@ -703,21 +701,21 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
703
  if ( $this->add_unsubscribe_link ) {
704
  $unsubscribe_message = get_option( 'ig_es_unsubscribe_link_content', '' );
705
  $unsubscribe_message = stripslashes( $unsubscribe_message );
706
- $content .= $unsubscribe_message;
707
  }
708
 
709
  $subject = $this->replace_global_tags( $subject );
710
  $subject = $this->mailer->convert_es_tags_to_mailer_tags( $subject );
711
-
712
  $content = $this->replace_global_tags( $content );
713
  $content = $this->mailer->convert_es_tags_to_mailer_tags( $content );
714
  $variable_string = $this->mailer->get_variable_string( 'contact_link_hash' );
715
  $content = $this->add_links_variables( $content, $campaign_id, $message_id, $variable_string );
716
-
717
  if ( $this->can_track_open() ) {
718
  $tracking_pixel_variable_name = $this->mailer->get_variable_prefix() . $this->mailer->get_variable_string( 'tracking_pixel_url' ) . $this->mailer->get_variable_suffix();
719
- $tracking_image = '<img src="' . $tracking_pixel_variable_name . '" width="1" height="1" alt=""/>';
720
- $content .= $tracking_image;
721
  }
722
 
723
  if ( $this->unsubscribe_headers_enabled() && is_callable( array( $this->mailer, 'set_list_unsubscribe_header' ) ) ) {
@@ -729,7 +727,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
729
  'sender_name' => $sender_name,
730
  'reply_to_email' => $reply_to_email,
731
  'subject' => $subject,
732
- 'content' => $content
733
  );
734
  $this->mailer->set_email_data( $email_data );
735
  }
@@ -758,7 +756,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
758
  );
759
 
760
  if ( $total_emails_to_send > 1 && $this->mailer->support_batch_sending ) {
761
-
762
  if ( ! $this->mailer->is_batch_limit_reached() ) {
763
  if ( 'single' === $this->mailer->batch_sending_mode ) {
764
  $message = $this->build_message( $subject, $content, $email, $merge_tags, $nl2br, $sender_data );
@@ -768,29 +766,29 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
768
  }
769
  }
770
 
771
- if ( ( $email_counter + 1 ) >= $total_emails_to_send || $this->mailer->is_batch_limit_reached() ) {
772
  $contact_ids = array_column( $this->mailer->batch_data, 'contact_id' );
773
  if ( ! empty( $contact_ids ) ) {
774
  do_action( 'ig_es_before_message_send', $contact_ids, $campaign_id, $message_id );
775
  }
776
  if ( 'multiple' === $this->mailer->batch_sending_mode ) {
777
- if ( ! empty( $sender_data['attachments'] )) {
778
  $this->mailer->set_attachments( $sender_data['attachments'] );
779
  }
780
  }
781
 
782
  $send_response = $this->mailer->send_batch();
783
-
784
  if ( ! is_wp_error( $send_response ) ) {
785
-
786
  if ( ! empty( $contact_ids ) ) {
787
  do_action( 'ig_es_message_sent', $contact_ids, $campaign_id, $message_id );
788
  }
789
  }
790
-
791
  $this->email_limit -= $this->mailer->current_batch_size;
792
  $this->mailer->clear_batch();
793
-
794
  // Error Sending Email?
795
  if ( is_wp_error( $send_response ) ) {
796
  $response['status'] = 'ERROR';
@@ -800,34 +798,34 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
800
  }
801
  } else {
802
  do_action( 'ig_es_before_message_send', $contact_id, $campaign_id, $message_id );
803
-
804
  $message = $this->build_message( $subject, $content, $email, $merge_tags, $nl2br, $sender_data );
805
-
806
  // object | WP_Error
807
  $send_response = $this->mailer->send( $message );
808
-
809
  // Error Sending Email?
810
  if ( is_wp_error( $send_response ) ) {
811
  $response['status'] = 'ERROR';
812
  $response['message'] = $send_response->get_error_messages();
813
-
814
  do_action( 'ig_es_email_sending_error', $contact_id, $campaign_id, $message_id, $response );
815
-
816
  // TODO: Log somewhere
817
  }
818
-
819
  do_action( 'ig_es_message_sent', $contact_id, $campaign_id, $message_id );
820
-
821
  // Reduce Email Sending Limit for this hour
822
  $this->email_limit --;
823
-
824
  }
825
 
826
  if ( $this->limits_exceeded() ) {
827
 
828
  if ( $this->mailer->support_batch_sending && ! empty( $this->mailer->batch_data ) ) {
829
  if ( 'multiple' === $this->mailer->batch_sending_mode ) {
830
- if ( ! empty( $sender_data['attachments'] )) {
831
  $this->mailer->set_attachments( $sender_data['attachments'] );
832
  }
833
  }
@@ -839,10 +837,10 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
839
  do_action( 'ig_es_message_sent', $contact_ids, $campaign_id, $message_id );
840
  }
841
  }
842
-
843
  $this->email_limit -= $this->mailer->current_batch_size;
844
  $this->mailer->clear_batch();
845
-
846
  // Error Sending Email?
847
  if ( is_wp_error( $send_response ) ) {
848
  $response['status'] = 'ERROR';
@@ -887,10 +885,10 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
887
  $attachments = array();
888
  // If sender data is passed .i.g. set in the campaign then use it.
889
  if ( ! empty( $sender_data ) ) {
890
- $sender_name = ! empty( $sender_data['from_name'] ) ? $sender_data['from_name'] : '';
891
- $sender_email = ! empty( $sender_data['from_email'] ) ? $sender_data['from_email'] : '';
892
- $reply_to_email = ! empty( $sender_data['reply_to_email'] ) ? $sender_data['reply_to_email']: '';
893
- $attachments = ! empty( $sender_data['attachments'] ) ? $sender_data['attachments'] : array();
894
  }
895
 
896
  // If sender name is not passed then fetch it from ES settings.
@@ -911,7 +909,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
911
  $charset = get_bloginfo( 'charset' );
912
 
913
  $subject = html_entity_decode( $subject, ENT_QUOTES, $charset );
914
-
915
  $message->from = $sender_email;
916
  $message->from_name = $sender_name;
917
  $message->to = $email;
@@ -925,7 +923,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
925
  "From: \"$message->from_name\" <$message->from>",
926
  'Return-Path: <' . $message->from . '>',
927
  'Reply-To: <' . $message->reply_to_email . '>',
928
- 'Content-Type: text/html; charset="' . $message->charset . '"'
929
  );
930
 
931
  $list_unsub_header = $this->get_list_unsubscribe_header( $email );
@@ -1121,7 +1119,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1121
  'contact_id' => $contact_id,
1122
  'email' => $email,
1123
  'guid' => $hash,
1124
- 'list_ids' => $list_ids,
1125
  );
1126
 
1127
  $this->link_data = $link_data;
@@ -1166,7 +1164,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1166
  * @since 4.7.0
1167
  */
1168
  public function replace_global_tags( $content = '', $merge_tags = array() ) {
1169
-
1170
  $blog_name = get_option( 'blogname' );
1171
  $total_contacts = ES()->contacts_db->get_total_contacts();
1172
  $site_url = home_url( '/' );
@@ -1300,7 +1298,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1300
 
1301
  $link = ' href="' . $link . '"';
1302
  $new_link = ' href="' . $new_link . '"';
1303
- $pos = strpos( $content, $link );
1304
  if ( false != $pos ) {
1305
  $content = preg_replace( '/' . preg_quote( $link, '/' ) . '/', $new_link, $content, 1 );
1306
  }
@@ -1323,7 +1321,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1323
  * @since 4.7.0
1324
  */
1325
  public function add_links_variables( $content, $campaign_id, $message_id, $variable_string = '' ) {
1326
- $this->mailer->links = array();
1327
  if ( $this->can_track_clicks() ) {
1328
 
1329
  // get all links from the basecontent
@@ -1367,9 +1365,9 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1367
  ES()->links_db->insert( $link_data );
1368
  }
1369
 
1370
- if ( ! empty( $hash )) {
1371
-
1372
- $hash_data = array(
1373
  'action' => 'click',
1374
  'link_hash' => $hash,
1375
  'contact_id' => '0',
@@ -1379,10 +1377,10 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1379
  $encoded_string = rtrim( base64_encode( $json_string ), '=' );
1380
  // Here we are replacing base64 encoded string with variable string in new link i.e. '"contact_id":"0"}' with contact_link_hash
1381
  $new_link = str_replace( $encoded_string, $variable_string, $new_link );
1382
-
1383
  $old_link = ' href="' . $link . '"';
1384
  $new_link = ' href="' . $new_link . '"';
1385
- $pos = strpos( $content, $old_link );
1386
  if ( false !== $pos ) {
1387
  $content = preg_replace( '/' . preg_quote( $old_link, '/' ) . '/', $new_link, $content, 1 );
1388
  }
@@ -1395,17 +1393,17 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1395
 
1396
  /**
1397
  * Get mailer specific link variables
1398
- *
1399
  * @param $contact_id
1400
- *
1401
  * @return array $link_variables
1402
- *
1403
  * @since 4.7.0
1404
- *
1405
  * @since 4.7.7 Returning only contact specific data
1406
  */
1407
  public function get_link_variable( $contact_id ) {
1408
-
1409
  $link_variables = array();
1410
  $json_string = '"contact_id":"' . $contact_id . '"}';
1411
 
@@ -1419,15 +1417,15 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1419
 
1420
  /**
1421
  * Get tracking url
1422
- *
1423
  * @param $link_data
1424
- *
1425
  * @return string $tracking_pixel_url
1426
- *
1427
  * @since 4.7.0
1428
  */
1429
  public function get_tracking_pixel_url( $link_data = array() ) {
1430
-
1431
  $tracking_pixel_url = '';
1432
 
1433
  if ( ! empty( $link_data ) && $this->can_track_open() ) {
@@ -1739,9 +1737,9 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1739
 
1740
  /**
1741
  * Get list unsubscribe header string
1742
- *
1743
  * @return string $list_unsub_header
1744
- *
1745
  * @since 4.7.2
1746
  */
1747
  public function get_list_unsubscribe_header( $email ) {
@@ -1751,7 +1749,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1751
  // Check if it is an campaign email and unsubscribe headers are enabled on the site.
1752
  if ( $this->unsubscribe_headers_enabled() ) {
1753
  $unsubscribe_link = $this->get_unsubscribe_link( $this->link_data );
1754
-
1755
  /* translators: 1. Subscriber email 2. Blog name */
1756
  $mail_to_subject = sprintf( __( 'Unsubscribe %1$s from %2$s', 'email-subscribers' ), $email, get_bloginfo( 'name' ) );
1757
  $list_unsub_header = sprintf(
@@ -1768,9 +1766,9 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1768
 
1769
  /**
1770
  * Check if List-Unsubcribe headers are enabled
1771
- *
1772
  * @return boolean $enabled
1773
- *
1774
  * @since 4.7.2
1775
  */
1776
  public function unsubscribe_headers_enabled() {
@@ -1783,9 +1781,9 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1783
 
1784
  /**
1785
  * Get default phpmailer
1786
- *
1787
  * @return PHPMailer
1788
- *
1789
  * @since 4.7.7
1790
  */
1791
  public function get_phpmailer() {
@@ -1799,7 +1797,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1799
  require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
1800
  require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
1801
  require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
1802
-
1803
  // Check if PHPMailer class already exists before creating an alias for it.
1804
  if ( ! class_exists( 'PHPMailer' ) ) {
1805
  class_alias( PHPMailer\PHPMailer\PHPMailer::class, 'PHPMailer' );
@@ -1816,7 +1814,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1816
  }
1817
  }
1818
 
1819
- $phpmailer = new PHPMailer( true );
1820
  $phpmailer->CharSet = 'UTF-8';
1821
 
1822
  return $phpmailer;
146
 
147
  // Add filter to increase memory limit
148
  add_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' );
149
+
150
  wp_raise_memory_limit( 'ig_es' );
151
 
152
  // Remove the added filter function so that it won't be called again if wp_raise_memory_limit called later on.
162
 
163
  /**
164
  * Check if memory limit is exceeded
165
+ *
166
  * For mailers supporting batch APIs, since we need to prepare and store subscriber's email data before dispatching it
167
  * memory limit can be reached in that case.
 
168
  */
169
  if ( IG_ES_Background_Process_Helper::memory_exceeded() ) {
170
  return true;
198
 
199
  $subject = $this->get_admin_new_contact_email_subject();
200
  $subject = $this->replace_admin_notification_merge_tags( $data, $subject );
201
+
202
  $content = $this->get_admin_new_contact_email_content();
203
  $content = $this->replace_admin_notification_merge_tags( $data, $content );
204
 
335
 
336
  $email_count = $notification['count'];
337
  $post_subject = $notification['subject'];
338
+ $cron_date = gmdate( 'Y-m-d H:i:s' );
339
  $cron_local_date = get_date_from_gmt( $cron_date ); // Convert from GMT to local date/time based on WordPress time zone setting.
340
+ $cron_date = ES_Common::convert_date_to_wp_date( $cron_local_date ); // Get formatted date from WordPress date/time settings.
341
 
342
  $content = str_replace( '{{DATE}}', $cron_date, $content );
343
  $content = str_replace( '{{COUNT}}', $email_count, $content );
589
  if ( ! empty( $campaign ) ) {
590
  $campaign_type = $campaign['type'];
591
  if ( 'newsletter' === $campaign_type ) {
592
+ $from_name = ! empty( $campaign['from_name'] ) ? $campaign['from_name'] : '';
593
+ $from_email = ! empty( $campaign['from_email'] ) ? $campaign['from_email'] : '';
594
+ $reply_to_email = ! empty( $campaign['reply_to_email'] ) ? $campaign['reply_to_email'] : '';
595
  $sender_data['from_name'] = $from_name;
596
  $sender_data['from_email'] = $from_email;
597
  $sender_data['reply_to_email'] = $reply_to_email;
648
  $this->email_id_map = ES_DB_Sending_Queue::get_emails_id_map_by_campaign( $campaign_id, $emails );
649
  }
650
  }
 
651
 
652
  $total_emails_to_send = count( $emails );
653
+
654
  // In case mailser supporting batch APIs, we are setting API credentials, sender data before running the email loop
655
  // For normal mailers, we are doing this inside the loop
656
  if ( $total_emails_to_send > 1 && $this->mailer->support_batch_sending ) {
657
+
658
  $mailer_data_set = $this->mailer->set_mailer_data();
659
+
660
  // Error setting up mailer?
661
  if ( is_wp_error( $mailer_data_set ) ) {
662
  $response['status'] = 'ERROR';
692
  } elseif ( empty( $reply_to_email ) ) {
693
  $reply_to_email = $this->get_from_email();
694
  }
695
+
696
  $charset = get_bloginfo( 'charset' );
697
  $subject = html_entity_decode( $subject, ENT_QUOTES, $charset );
698
  $content = preg_replace( '/data-json=".*?"/is', '', $content );
701
  if ( $this->add_unsubscribe_link ) {
702
  $unsubscribe_message = get_option( 'ig_es_unsubscribe_link_content', '' );
703
  $unsubscribe_message = stripslashes( $unsubscribe_message );
704
+ $content .= $unsubscribe_message;
705
  }
706
 
707
  $subject = $this->replace_global_tags( $subject );
708
  $subject = $this->mailer->convert_es_tags_to_mailer_tags( $subject );
709
+
710
  $content = $this->replace_global_tags( $content );
711
  $content = $this->mailer->convert_es_tags_to_mailer_tags( $content );
712
  $variable_string = $this->mailer->get_variable_string( 'contact_link_hash' );
713
  $content = $this->add_links_variables( $content, $campaign_id, $message_id, $variable_string );
714
+
715
  if ( $this->can_track_open() ) {
716
  $tracking_pixel_variable_name = $this->mailer->get_variable_prefix() . $this->mailer->get_variable_string( 'tracking_pixel_url' ) . $this->mailer->get_variable_suffix();
717
+ $tracking_image = '<img src="' . $tracking_pixel_variable_name . '" width="1" height="1" alt=""/>';
718
+ $content .= $tracking_image;
719
  }
720
 
721
  if ( $this->unsubscribe_headers_enabled() && is_callable( array( $this->mailer, 'set_list_unsubscribe_header' ) ) ) {
727
  'sender_name' => $sender_name,
728
  'reply_to_email' => $reply_to_email,
729
  'subject' => $subject,
730
+ 'content' => $content,
731
  );
732
  $this->mailer->set_email_data( $email_data );
733
  }
756
  );
757
 
758
  if ( $total_emails_to_send > 1 && $this->mailer->support_batch_sending ) {
759
+
760
  if ( ! $this->mailer->is_batch_limit_reached() ) {
761
  if ( 'single' === $this->mailer->batch_sending_mode ) {
762
  $message = $this->build_message( $subject, $content, $email, $merge_tags, $nl2br, $sender_data );
766
  }
767
  }
768
 
769
+ if ( ( $email_counter + 1 ) >= $total_emails_to_send || $this->mailer->is_batch_limit_reached() ) {
770
  $contact_ids = array_column( $this->mailer->batch_data, 'contact_id' );
771
  if ( ! empty( $contact_ids ) ) {
772
  do_action( 'ig_es_before_message_send', $contact_ids, $campaign_id, $message_id );
773
  }
774
  if ( 'multiple' === $this->mailer->batch_sending_mode ) {
775
+ if ( ! empty( $sender_data['attachments'] ) ) {
776
  $this->mailer->set_attachments( $sender_data['attachments'] );
777
  }
778
  }
779
 
780
  $send_response = $this->mailer->send_batch();
781
+
782
  if ( ! is_wp_error( $send_response ) ) {
783
+
784
  if ( ! empty( $contact_ids ) ) {
785
  do_action( 'ig_es_message_sent', $contact_ids, $campaign_id, $message_id );
786
  }
787
  }
788
+
789
  $this->email_limit -= $this->mailer->current_batch_size;
790
  $this->mailer->clear_batch();
791
+
792
  // Error Sending Email?
793
  if ( is_wp_error( $send_response ) ) {
794
  $response['status'] = 'ERROR';
798
  }
799
  } else {
800
  do_action( 'ig_es_before_message_send', $contact_id, $campaign_id, $message_id );
801
+
802
  $message = $this->build_message( $subject, $content, $email, $merge_tags, $nl2br, $sender_data );
803
+
804
  // object | WP_Error
805
  $send_response = $this->mailer->send( $message );
806
+
807
  // Error Sending Email?
808
  if ( is_wp_error( $send_response ) ) {
809
  $response['status'] = 'ERROR';
810
  $response['message'] = $send_response->get_error_messages();
811
+
812
  do_action( 'ig_es_email_sending_error', $contact_id, $campaign_id, $message_id, $response );
813
+
814
  // TODO: Log somewhere
815
  }
816
+
817
  do_action( 'ig_es_message_sent', $contact_id, $campaign_id, $message_id );
818
+
819
  // Reduce Email Sending Limit for this hour
820
  $this->email_limit --;
821
+
822
  }
823
 
824
  if ( $this->limits_exceeded() ) {
825
 
826
  if ( $this->mailer->support_batch_sending && ! empty( $this->mailer->batch_data ) ) {
827
  if ( 'multiple' === $this->mailer->batch_sending_mode ) {
828
+ if ( ! empty( $sender_data['attachments'] ) ) {
829
  $this->mailer->set_attachments( $sender_data['attachments'] );
830
  }
831
  }
837
  do_action( 'ig_es_message_sent', $contact_ids, $campaign_id, $message_id );
838
  }
839
  }
840
+
841
  $this->email_limit -= $this->mailer->current_batch_size;
842
  $this->mailer->clear_batch();
843
+
844
  // Error Sending Email?
845
  if ( is_wp_error( $send_response ) ) {
846
  $response['status'] = 'ERROR';
885
  $attachments = array();
886
  // If sender data is passed .i.g. set in the campaign then use it.
887
  if ( ! empty( $sender_data ) ) {
888
+ $sender_name = ! empty( $sender_data['from_name'] ) ? $sender_data['from_name'] : '';
889
+ $sender_email = ! empty( $sender_data['from_email'] ) ? $sender_data['from_email'] : '';
890
+ $reply_to_email = ! empty( $sender_data['reply_to_email'] ) ? $sender_data['reply_to_email'] : '';
891
+ $attachments = ! empty( $sender_data['attachments'] ) ? $sender_data['attachments'] : array();
892
  }
893
 
894
  // If sender name is not passed then fetch it from ES settings.
909
  $charset = get_bloginfo( 'charset' );
910
 
911
  $subject = html_entity_decode( $subject, ENT_QUOTES, $charset );
912
+
913
  $message->from = $sender_email;
914
  $message->from_name = $sender_name;
915
  $message->to = $email;
923
  "From: \"$message->from_name\" <$message->from>",
924
  'Return-Path: <' . $message->from . '>',
925
  'Reply-To: <' . $message->reply_to_email . '>',
926
+ 'Content-Type: text/html; charset="' . $message->charset . '"',
927
  );
928
 
929
  $list_unsub_header = $this->get_list_unsubscribe_header( $email );
1119
  'contact_id' => $contact_id,
1120
  'email' => $email,
1121
  'guid' => $hash,
1122
+ 'list_ids' => $list_ids,
1123
  );
1124
 
1125
  $this->link_data = $link_data;
1164
  * @since 4.7.0
1165
  */
1166
  public function replace_global_tags( $content = '', $merge_tags = array() ) {
1167
+
1168
  $blog_name = get_option( 'blogname' );
1169
  $total_contacts = ES()->contacts_db->get_total_contacts();
1170
  $site_url = home_url( '/' );
1298
 
1299
  $link = ' href="' . $link . '"';
1300
  $new_link = ' href="' . $new_link . '"';
1301
+ $pos = strpos( $content, $link );
1302
  if ( false != $pos ) {
1303
  $content = preg_replace( '/' . preg_quote( $link, '/' ) . '/', $new_link, $content, 1 );
1304
  }
1321
  * @since 4.7.0
1322
  */
1323
  public function add_links_variables( $content, $campaign_id, $message_id, $variable_string = '' ) {
1324
+ $this->mailer->links = array();
1325
  if ( $this->can_track_clicks() ) {
1326
 
1327
  // get all links from the basecontent
1365
  ES()->links_db->insert( $link_data );
1366
  }
1367
 
1368
+ if ( ! empty( $hash ) ) {
1369
+
1370
+ $hash_data = array(
1371
  'action' => 'click',
1372
  'link_hash' => $hash,
1373
  'contact_id' => '0',
1377
  $encoded_string = rtrim( base64_encode( $json_string ), '=' );
1378
  // Here we are replacing base64 encoded string with variable string in new link i.e. '"contact_id":"0"}' with contact_link_hash
1379
  $new_link = str_replace( $encoded_string, $variable_string, $new_link );
1380
+
1381
  $old_link = ' href="' . $link . '"';
1382
  $new_link = ' href="' . $new_link . '"';
1383
+ $pos = strpos( $content, $old_link );
1384
  if ( false !== $pos ) {
1385
  $content = preg_replace( '/' . preg_quote( $old_link, '/' ) . '/', $new_link, $content, 1 );
1386
  }
1393
 
1394
  /**
1395
  * Get mailer specific link variables
1396
+ *
1397
  * @param $contact_id
1398
+ *
1399
  * @return array $link_variables
1400
+ *
1401
  * @since 4.7.0
1402
+ *
1403
  * @since 4.7.7 Returning only contact specific data
1404
  */
1405
  public function get_link_variable( $contact_id ) {
1406
+
1407
  $link_variables = array();
1408
  $json_string = '"contact_id":"' . $contact_id . '"}';
1409
 
1417
 
1418
  /**
1419
  * Get tracking url
1420
+ *
1421
  * @param $link_data
1422
+ *
1423
  * @return string $tracking_pixel_url
1424
+ *
1425
  * @since 4.7.0
1426
  */
1427
  public function get_tracking_pixel_url( $link_data = array() ) {
1428
+
1429
  $tracking_pixel_url = '';
1430
 
1431
  if ( ! empty( $link_data ) && $this->can_track_open() ) {
1737
 
1738
  /**
1739
  * Get list unsubscribe header string
1740
+ *
1741
  * @return string $list_unsub_header
1742
+ *
1743
  * @since 4.7.2
1744
  */
1745
  public function get_list_unsubscribe_header( $email ) {
1749
  // Check if it is an campaign email and unsubscribe headers are enabled on the site.
1750
  if ( $this->unsubscribe_headers_enabled() ) {
1751
  $unsubscribe_link = $this->get_unsubscribe_link( $this->link_data );
1752
+
1753
  /* translators: 1. Subscriber email 2. Blog name */
1754
  $mail_to_subject = sprintf( __( 'Unsubscribe %1$s from %2$s', 'email-subscribers' ), $email, get_bloginfo( 'name' ) );
1755
  $list_unsub_header = sprintf(
1766
 
1767
  /**
1768
  * Check if List-Unsubcribe headers are enabled
1769
+ *
1770
  * @return boolean $enabled
1771
+ *
1772
  * @since 4.7.2
1773
  */
1774
  public function unsubscribe_headers_enabled() {
1781
 
1782
  /**
1783
  * Get default phpmailer
1784
+ *
1785
  * @return PHPMailer
1786
+ *
1787
  * @since 4.7.7
1788
  */
1789
  public function get_phpmailer() {
1797
  require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
1798
  require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
1799
  require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
1800
+
1801
  // Check if PHPMailer class already exists before creating an alias for it.
1802
  if ( ! class_exists( 'PHPMailer' ) ) {
1803
  class_alias( PHPMailer\PHPMailer\PHPMailer::class, 'PHPMailer' );
1814
  }
1815
  }
1816
 
1817
+ $phpmailer = new PHPMailer( true );
1818
  $phpmailer->CharSet = 'UTF-8';
1819
 
1820
  return $phpmailer;
lite/includes/classes/class-es-message.php CHANGED
@@ -94,21 +94,21 @@ if ( ! class_exists( 'ES_Message' ) ) {
94
 
95
  /**
96
  * Attachments for email
97
- *
98
  * @since 4.6.7
99
  */
100
  public $attachments = array();
101
 
102
  /**
103
  * Reply to email
104
- *
105
  * @since 4.6.7
106
  */
107
  public $reply_to_email = '';
108
 
109
  /**
110
  * Character set
111
- *
112
  * @since 4.6.7
113
  */
114
  public $charset = '';
94
 
95
  /**
96
  * Attachments for email
97
+ *
98
  * @since 4.6.7
99
  */
100
  public $attachments = array();
101
 
102
  /**
103
  * Reply to email
104
+ *
105
  * @since 4.6.7
106
  */
107
  public $reply_to_email = '';
108
 
109
  /**
110
  * Character set
111
+ *
112
  * @since 4.6.7
113
  */
114
  public $charset = '';
lite/includes/classes/class-es-newsletters.php CHANGED
@@ -54,10 +54,10 @@ class ES_Newsletters {
54
  public function process_broadcast_submission() {
55
 
56
  global $wpdb;
57
-
58
  $submitted = ig_es_get_request_data( 'ig_es_broadcast_submitted' );
59
  $broadcast_data = ig_es_get_request_data( 'broadcast_data', array(), false );
60
-
61
  if ( 'submitted' === $submitted ) {
62
  $broadcast_nonce = ig_es_get_request_data( 'ig_es_broadcast_nonce' );
63
  // Verify nonce.
@@ -142,17 +142,17 @@ class ES_Newsletters {
142
 
143
  $broadcast = array_shift( $broadcasts );
144
  $broadcast_data = array(
145
- 'id' => $broadcast['id'],
146
- 'name' => $broadcast['name'],
147
- 'subject' => $broadcast['subject'],
148
- 'from_name' => $broadcast['from_name'],
149
- 'from_email' => $broadcast['from_email'],
150
  'reply_to_email' => $broadcast['reply_to_email'],
151
- 'body' => $broadcast['body'],
152
- 'list_ids' => $broadcast['list_ids'],
153
- 'template_id' => $broadcast['base_template_id'],
154
- 'status' => $broadcast['status'],
155
- 'meta' => maybe_unserialize( $broadcast['meta'] ),
156
  );
157
  }
158
 
@@ -315,13 +315,13 @@ class ES_Newsletters {
315
  ?>
316
  <button type="submit" id="ig_es_broadcast_submitted" name="ig_es_broadcast_submitted" class="w-24 inline-flex justify-center py-1.5 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-transparent rounded-md md:px-2 lg:px-3 xl:px-4 hover:bg-indigo-500 hover:text-white"
317
  value="submitted">
318
- <?php
319
- if ( ES()->is_pro() ) {
320
  ?>
321
  <span class="ig_es_broadcast_send_option_text">
322
  <?php echo esc_html__( 'Schedule', 'email-subscribers' ); ?>
323
  </span>
324
- <?php
325
  } else {
326
  echo esc_html__( 'Send', 'email-subscribers' );
327
  }
@@ -335,7 +335,7 @@ class ES_Newsletters {
335
  <div class="ml-1 xl:ml-2 mt-2">
336
  <a class="px-1.5 py-2 es-documentation" href="https://www.icegram.com/documentation/es-how-to-create-and-send-newsletter-emails/?utm_source=in_app&utm_medium=broadcast&utm_campaign=es_doc" target="_blank">
337
  <svg class="w-6 h-6 -mt-1 inline text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
338
- <title><?php esc_html_e('Documentation ', 'email-subscribers'); ?></title>
339
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
340
  </svg>
341
  </a>
@@ -390,8 +390,8 @@ class ES_Newsletters {
390
  <div class="block pt-6 mx-4 pb-3">
391
  <label for="template" class="text-sm font-medium leading-5 text-gray-700"><?php echo esc_html__( 'Design template', 'email-subscribers' ); ?></label>
392
  <select class="block w-full h-8 mt-1 text-sm rounded-md cursor-pointer h-9 form-select" name="broadcast_data[template_id]" id="base_template_id">
393
- <?php
394
- echo wp_kses( $templates, $allowedtags );
395
  ?>
396
  </select>
397
  </div>
@@ -472,7 +472,7 @@ class ES_Newsletters {
472
  </div>
473
  <div class="block mt-3">
474
  <span class="text-sm font-bold text-gray-800 broadcast_preview_contact_name"><?php echo ! empty( $inline_preview_data['contact_name'] ) ? esc_html( $inline_preview_data['contact_name'] ) : ''; ?></span>
475
- <span class="pl-1 text-sm font-medium text-gray-700 broadcast_preview_contact_email"><?php echo ! empty( $inline_preview_data['contact_email'] ) ? esc_html('&lt;' . $inline_preview_data['contact_email'] . '&gt;' ) : ''; ?></span>
476
  </div>
477
  <div class="block mt-3 broadcast_preview_content">
478
  <?php
@@ -483,7 +483,7 @@ class ES_Newsletters {
483
  ob_start();
484
  $this->es_broadcast_preview_callback( $template_data );
485
  $tempate_html = ob_get_clean();
486
- echo wp_kses( $tempate_html, $allowedtags);
487
  }
488
  ?>
489
  </div>
@@ -563,8 +563,8 @@ class ES_Newsletters {
563
  $notification = ES_DB_Mailing_Queue::get_notification_by_campaign_id( $campaign_id );
564
  $data['body'] = ES_Common::es_process_template_body( $data['body'], $data['base_template_id'], $campaign_id );
565
 
566
- $guid = ES_Common::generate_guid( 6 );
567
- $data = array(
568
  'hash' => $guid,
569
  'campaign_id' => $campaign_id,
570
  'subject' => $data['subject'],
@@ -596,21 +596,21 @@ class ES_Newsletters {
596
  $data['hash'] = $notification['hash'];
597
  $data['campaign_id'] = $notification['campaign_id'];
598
  $data['created_at'] = $notification['created_at'];
599
-
600
  // Check if list has been updated, if yes then we need to delete emails from existing lists and requeue the emails from the updated lists.
601
  if ( $selected_list_ids !== $existing_list_ids ) {
602
  $should_queue_emails = true;
603
  $data['count'] = 0;
604
  } else {
605
- $data['count'] = $notification['count'];
606
  }
607
 
608
- $notification = ES_DB_Mailing_Queue::update_notification( $mailing_queue_id, $data );
609
  }
610
  }
611
 
612
  if ( ! empty( $mailing_queue_id ) ) {
613
-
614
  if ( $should_queue_emails ) {
615
 
616
  // Delete existing sending queue if any already present.
@@ -618,14 +618,14 @@ class ES_Newsletters {
618
 
619
  ES_DB_Sending_Queue::do_insert_from_contacts_table( $mailing_queue_id, $mailing_queue_hash, $campaign_id, $list_id );
620
  }
621
-
622
  $mailing_queue = ES_DB_Mailing_Queue::get_mailing_queue_by_id( $mailing_queue_id );
623
  if ( ! empty( $mailing_queue ) ) {
624
-
625
  $queue_start_at = $mailing_queue['start_at'];
626
  $current_timestamp = time();
627
  $sending_timestamp = strtotime( $queue_start_at );
628
-
629
  // Check if campaign sending time has come.
630
  if ( ! empty( $sending_timestamp ) && $sending_timestamp <= $current_timestamp ) {
631
  $request_args = array(
@@ -635,7 +635,6 @@ class ES_Newsletters {
635
  // Send an asynchronous request to trigger sending of campaign emails.
636
  IG_ES_Background_Process_Helper::send_async_ajax_request( $request_args, true );
637
  }
638
-
639
  }
640
  }
641
  }
@@ -699,7 +698,7 @@ class ES_Newsletters {
699
  $es_template_body = str_replace( '{{EMAIL}}', $useremail, $es_template_body );
700
  $es_template_body = str_replace( '{{FIRSTNAME}}', $first_name, $es_template_body );
701
  $es_template_body = str_replace( '{{LASTNAME}}', $last_name, $es_template_body );
702
- $allowedtags = ig_es_allowed_html_tags_in_esc();
703
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
704
 
705
  if ( has_post_thumbnail( $template_id ) ) {
@@ -728,7 +727,7 @@ class ES_Newsletters {
728
  <div class="es-clear-preview"></div>
729
  </div>
730
  </div>';
731
- echo wp_kses( apply_filters( 'the_content', $html ), $allowedtags);
732
  }
733
 
734
  }
@@ -748,10 +747,10 @@ class ES_Newsletters {
748
 
749
  $broadcast_data = ig_es_get_request_data( 'broadcast_data', array(), false );
750
 
751
- /**
752
- * To allow insert of new broadcast data,
753
  * we are specifically setting $broadcast_id to null when id is empty in $broadcast_data
754
- **/
755
  $broadcast_id = ! empty( $broadcast_data['id'] ) ? $broadcast_data['id'] : null;
756
  $is_updating = ! empty( $broadcast_id ) ? true : false;
757
  $list_id = ! empty( $broadcast_data['list_ids'] ) ? $broadcast_data['list_ids'] : '';
54
  public function process_broadcast_submission() {
55
 
56
  global $wpdb;
57
+
58
  $submitted = ig_es_get_request_data( 'ig_es_broadcast_submitted' );
59
  $broadcast_data = ig_es_get_request_data( 'broadcast_data', array(), false );
60
+
61
  if ( 'submitted' === $submitted ) {
62
  $broadcast_nonce = ig_es_get_request_data( 'ig_es_broadcast_nonce' );
63
  // Verify nonce.
142
 
143
  $broadcast = array_shift( $broadcasts );
144
  $broadcast_data = array(
145
+ 'id' => $broadcast['id'],
146
+ 'name' => $broadcast['name'],
147
+ 'subject' => $broadcast['subject'],
148
+ 'from_name' => $broadcast['from_name'],
149
+ 'from_email' => $broadcast['from_email'],
150
  'reply_to_email' => $broadcast['reply_to_email'],
151
+ 'body' => $broadcast['body'],
152
+ 'list_ids' => $broadcast['list_ids'],
153
+ 'template_id' => $broadcast['base_template_id'],
154
+ 'status' => $broadcast['status'],
155
+ 'meta' => maybe_unserialize( $broadcast['meta'] ),
156
  );
157
  }
158
 
315
  ?>
316
  <button type="submit" id="ig_es_broadcast_submitted" name="ig_es_broadcast_submitted" class="w-24 inline-flex justify-center py-1.5 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-transparent rounded-md md:px-2 lg:px-3 xl:px-4 hover:bg-indigo-500 hover:text-white"
317
  value="submitted">
318
+ <?php
319
+ if ( ES()->is_pro() ) {
320
  ?>
321
  <span class="ig_es_broadcast_send_option_text">
322
  <?php echo esc_html__( 'Schedule', 'email-subscribers' ); ?>
323
  </span>
324
+ <?php
325
  } else {
326
  echo esc_html__( 'Send', 'email-subscribers' );
327
  }
335
  <div class="ml-1 xl:ml-2 mt-2">
336
  <a class="px-1.5 py-2 es-documentation" href="https://www.icegram.com/documentation/es-how-to-create-and-send-newsletter-emails/?utm_source=in_app&utm_medium=broadcast&utm_campaign=es_doc" target="_blank">
337
  <svg class="w-6 h-6 -mt-1 inline text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
338
+ <title><?php esc_html_e( 'Documentation ', 'email-subscribers' ); ?></title>
339
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
340
  </svg>
341
  </a>
390
  <div class="block pt-6 mx-4 pb-3">
391
  <label for="template" class="text-sm font-medium leading-5 text-gray-700"><?php echo esc_html__( 'Design template', 'email-subscribers' ); ?></label>
392
  <select class="block w-full h-8 mt-1 text-sm rounded-md cursor-pointer h-9 form-select" name="broadcast_data[template_id]" id="base_template_id">
393
+ <?php
394
+ echo wp_kses( $templates, $allowedtags );
395
  ?>
396
  </select>
397
  </div>
472
  </div>
473
  <div class="block mt-3">
474
  <span class="text-sm font-bold text-gray-800 broadcast_preview_contact_name"><?php echo ! empty( $inline_preview_data['contact_name'] ) ? esc_html( $inline_preview_data['contact_name'] ) : ''; ?></span>
475
+ <span class="pl-1 text-sm font-medium text-gray-700 broadcast_preview_contact_email"><?php echo ! empty( $inline_preview_data['contact_email'] ) ? esc_html( '&lt;' . $inline_preview_data['contact_email'] . '&gt;' ) : ''; ?></span>
476
  </div>
477
  <div class="block mt-3 broadcast_preview_content">
478
  <?php
483
  ob_start();
484
  $this->es_broadcast_preview_callback( $template_data );
485
  $tempate_html = ob_get_clean();
486
+ echo wp_kses( $tempate_html, $allowedtags );
487
  }
488
  ?>
489
  </div>
563
  $notification = ES_DB_Mailing_Queue::get_notification_by_campaign_id( $campaign_id );
564
  $data['body'] = ES_Common::es_process_template_body( $data['body'], $data['base_template_id'], $campaign_id );
565
 
566
+ $guid = ES_Common::generate_guid( 6 );
567
+ $data = array(
568
  'hash' => $guid,
569
  'campaign_id' => $campaign_id,
570
  'subject' => $data['subject'],
596
  $data['hash'] = $notification['hash'];
597
  $data['campaign_id'] = $notification['campaign_id'];
598
  $data['created_at'] = $notification['created_at'];
599
+
600
  // Check if list has been updated, if yes then we need to delete emails from existing lists and requeue the emails from the updated lists.
601
  if ( $selected_list_ids !== $existing_list_ids ) {
602
  $should_queue_emails = true;
603
  $data['count'] = 0;
604
  } else {
605
+ $data['count'] = $notification['count'];
606
  }
607
 
608
+ $notification = ES_DB_Mailing_Queue::update_notification( $mailing_queue_id, $data );
609
  }
610
  }
611
 
612
  if ( ! empty( $mailing_queue_id ) ) {
613
+
614
  if ( $should_queue_emails ) {
615
 
616
  // Delete existing sending queue if any already present.
618
 
619
  ES_DB_Sending_Queue::do_insert_from_contacts_table( $mailing_queue_id, $mailing_queue_hash, $campaign_id, $list_id );
620
  }
621
+
622
  $mailing_queue = ES_DB_Mailing_Queue::get_mailing_queue_by_id( $mailing_queue_id );
623
  if ( ! empty( $mailing_queue ) ) {
624
+
625
  $queue_start_at = $mailing_queue['start_at'];
626
  $current_timestamp = time();
627
  $sending_timestamp = strtotime( $queue_start_at );
628
+
629
  // Check if campaign sending time has come.
630
  if ( ! empty( $sending_timestamp ) && $sending_timestamp <= $current_timestamp ) {
631
  $request_args = array(
635
  // Send an asynchronous request to trigger sending of campaign emails.
636
  IG_ES_Background_Process_Helper::send_async_ajax_request( $request_args, true );
637
  }
 
638
  }
639
  }
640
  }
698
  $es_template_body = str_replace( '{{EMAIL}}', $useremail, $es_template_body );
699
  $es_template_body = str_replace( '{{FIRSTNAME}}', $first_name, $es_template_body );
700
  $es_template_body = str_replace( '{{LASTNAME}}', $last_name, $es_template_body );
701
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
702
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
703
 
704
  if ( has_post_thumbnail( $template_id ) ) {
727
  <div class="es-clear-preview"></div>
728
  </div>
729
  </div>';
730
+ echo wp_kses( apply_filters( 'the_content', $html ), $allowedtags );
731
  }
732
 
733
  }
747
 
748
  $broadcast_data = ig_es_get_request_data( 'broadcast_data', array(), false );
749
 
750
+ /**
751
+ * To allow insert of new broadcast data,
752
  * we are specifically setting $broadcast_id to null when id is empty in $broadcast_data
753
+ */
754
  $broadcast_id = ! empty( $broadcast_data['id'] ) ? $broadcast_data['id'] : null;
755
  $is_updating = ! empty( $broadcast_id ) ? true : false;
756
  $list_id = ! empty( $broadcast_data['list_ids'] ) ? $broadcast_data['list_ids'] : '';
lite/includes/classes/class-es-old-widget.php CHANGED
@@ -22,7 +22,7 @@ class ES_Old_Widget extends WP_Widget {
22
  echo wp_kses_post( $args['before_widget'] );
23
 
24
  if ( ! empty( $title ) ) {
25
- echo wp_kses_post( sprintf( '%s %s %s', $args['before_title'] , $title , $args['after_title']) );
26
  }
27
 
28
  $display_name = isset( $instance['es_name'] ) ? esc_attr( $instance['es_name'] ) : '';
@@ -96,10 +96,10 @@ class ES_Old_Widget extends WP_Widget {
96
  foreach ( $groups as $group ) {
97
  ?>
98
  <option value="<?php echo esc_attr( stripslashes( $group ) ); ?>"
99
- <?php
100
  if ( stripslashes( $es_group ) == $group ) {
101
  echo 'selected="selected"';
102
- }
103
  ?>
104
  >
105
  <?php echo esc_html( stripslashes( $group ) ); ?>
22
  echo wp_kses_post( $args['before_widget'] );
23
 
24
  if ( ! empty( $title ) ) {
25
+ echo wp_kses_post( sprintf( '%s %s %s', $args['before_title'], $title, $args['after_title'] ) );
26
  }
27
 
28
  $display_name = isset( $instance['es_name'] ) ? esc_attr( $instance['es_name'] ) : '';
96
  foreach ( $groups as $group ) {
97
  ?>
98
  <option value="<?php echo esc_attr( stripslashes( $group ) ); ?>"
99
+ <?php
100
  if ( stripslashes( $es_group ) == $group ) {
101
  echo 'selected="selected"';
102
+ }
103
  ?>
104
  >
105
  <?php echo esc_html( stripslashes( $group ) ); ?>
lite/includes/classes/class-es-post-notifications.php CHANGED
@@ -157,14 +157,14 @@ class ES_Post_Notifications_Table {
157
 
158
  if ( count( $query ) > 0 ) {
159
  $sql .= implode( ' AND ', $query );
160
- $sql = $wpbd->prepare( $sql, $args );
161
  }
162
  }
163
 
164
  // Prepare Order by clause
165
  $order_by_clause = '';
166
  if ( ! empty( $order_by ) ) {
167
- $order_by_clause = ' ORDER BY ' . esc_sql( $order_by );
168
  $order_by_clause .= ! empty( $order ) ? ' ' . esc_sql( $order ) : ' ASC';
169
  }
170
 
@@ -215,7 +215,7 @@ class ES_Post_Notifications_Table {
215
 
216
  $data = apply_filters( 'ig_es_post_notification_data', $data );
217
  $data['type'] = ! empty( $data['type'] ) ? $data['type'] : 'post_notification';
218
- //check tempalte id
219
  if ( empty( $data['base_template_id'] ) ) {
220
  $message = __( 'Please select template.', 'email-subscribers' );
221
  ES_Common::show_message( $message, 'error' );
157
 
158
  if ( count( $query ) > 0 ) {
159
  $sql .= implode( ' AND ', $query );
160
+ $sql = $wpbd->prepare( $sql, $args );
161
  }
162
  }
163
 
164
  // Prepare Order by clause
165
  $order_by_clause = '';
166
  if ( ! empty( $order_by ) ) {
167
+ $order_by_clause = ' ORDER BY ' . esc_sql( $order_by );
168
  $order_by_clause .= ! empty( $order ) ? ' ' . esc_sql( $order ) : ' ASC';
169
  }
170
 
215
 
216
  $data = apply_filters( 'ig_es_post_notification_data', $data );
217
  $data['type'] = ! empty( $data['type'] ) ? $data['type'] : 'post_notification';
218
+ // check tempalte id
219
  if ( empty( $data['base_template_id'] ) ) {
220
  $message = __( 'Please select template.', 'email-subscribers' );
221
  ES_Common::show_message( $message, 'error' );
lite/includes/classes/class-es-queue.php CHANGED
@@ -43,14 +43,14 @@ if ( ! class_exists( 'ES_Queue' ) ) {
43
  add_action( 'ig_es_message_sent', array( &$this, 'update_email_sent_count' ), 10, 3 );
44
  add_action( 'ig_es_contact_unsubscribe', array( &$this, 'delete_contact_queued_emails' ), 10, 4 );
45
  add_action( 'ig_es_admin_contact_unsubscribe', array( &$this, 'delete_contact_queued_emails' ), 10, 4 );
46
-
47
  // Action scheduler action to add subscribers to sending_queue table in background. Called through Action Scheduler library.
48
  add_action( 'ig_es_add_subscribers_to_sending_queue', array( &$this, 'add_subscribers_to_sending_queue' ) );
49
-
50
  // Ajax handler for running action scheduler task.
51
  add_action( 'wp_ajax_ig_es_run_action_scheduler_task', array( 'IG_ES_Background_Process_Helper', 'run_action_scheduler_task' ) );
52
  add_action( 'wp_ajax_nopriv_ig_es_run_action_scheduler_task', array( 'IG_ES_Background_Process_Helper', 'run_action_scheduler_task' ) );
53
-
54
  // Ajax handler for triggering email queue sending.
55
  add_action( 'wp_ajax_ig_es_trigger_mailing_queue_sending', array( $this, 'trigger_mailing_queue_sending' ) );
56
  add_action( 'wp_ajax_nopriv_ig_es_trigger_mailing_queue_sending', array( $this, 'trigger_mailing_queue_sending' ) );
@@ -170,7 +170,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
170
  if ( is_array( $result ) ) {
171
 
172
  $mailing_queue_id = $result['id'];
173
-
174
  if ( ! empty( $mailing_queue_id ) ) {
175
  $mailing_queue_hash = $result['hash'];
176
  ES_DB_Sending_Queue::do_insert_from_contacts_table( $mailing_queue_id, $mailing_queue_hash, $campaign_id, $list_id );
@@ -282,7 +282,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
282
  $list_ids = $campaign['list_ids'];
283
 
284
  $campaign = ES()->campaigns_db->get( $campaign_id );
285
-
286
  $conditions = array();
287
  if ( ! empty( $campaign ) && ! empty( $campaign['meta'] ) ) {
288
  $campaign_meta = maybe_unserialize( $campaign['meta'] );
@@ -293,19 +293,18 @@ if ( ! class_exists( 'ES_Queue' ) ) {
293
 
294
  $conditions = ! empty( $meta['list_conditions'] ) ? $meta['list_conditions'] : array();
295
 
296
-
297
  $query_args = array(
298
- 'select' => array(
299
  'lists_subscribers.contact_id AS contact_id',
300
  "UNIX_TIMESTAMP ( lists_subscribers.subscribed_at + INTERVAL $offset ) AS timestamp",
301
  ),
302
  'sent__not_in' => array( $campaign_id ),
303
  'queue__not_in' => array( $campaign_id ),
304
- 'lists' => $list_ids,
305
- 'conditions' => $conditions,
306
- 'having' => array( 'timestamp <= ' . ( $now + $queue_upfront ) ),
307
- 'orderby' => array( 'timestamp' ),
308
- 'groupby' => 'lists_subscribers.contact_id',
309
  );
310
 
311
  if ( $grace_period ) {
@@ -319,7 +318,6 @@ if ( ! class_exists( 'ES_Queue' ) ) {
319
  // ES()->logger->info( $query );
320
  // ES()->logger->info( '----------------------------Query Args Complete (ig_es_contact_insert) ----------------------------' );
321
 
322
-
323
  // ES()->logger->info( 'Results: ' . print_r( $results, true ) );
324
 
325
  if ( ! empty( $results ) ) {
@@ -544,7 +542,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
544
  * @since 4.2.1
545
  */
546
  public function process_queue() {
547
-
548
  global $wpdb;
549
 
550
  if ( ES()->cron->should_unlock() ) {
@@ -552,17 +550,17 @@ if ( ! class_exists( 'ES_Queue' ) ) {
552
  }
553
 
554
  ES()->cron->set_last_hit();
555
-
556
  $email_sending_limit = ES()->mailer->get_total_emails_send_now();
557
 
558
  if ( $email_sending_limit > 0 ) {
559
 
560
  $micro_time = microtime( true );
561
-
562
  // ES()->logger->info( 'Process Queue:' );
563
  // ES()->logger->info( 'SQL: ' . $sql );
564
-
565
- $notifications = $wpdb->get_results(
566
  $wpdb->prepare(
567
  "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
568
  FROM {$wpdb->prefix}ig_queue AS queue
@@ -570,40 +568,40 @@ if ( ! class_exists( 'ES_Queue' ) ) {
570
  WHERE queue.timestamp <= %d AND queue.sent_at = 0
571
  AND (campaigns.status = 1 OR queue.ignore_status = 1)
572
  ORDER BY queue.priority DESC",
573
- (int) $micro_time
574
  ),
575
  ARRAY_A
576
  );
577
-
578
  $batch_start_time = time();
579
-
580
  if ( is_array( $notifications ) && count( $notifications ) > 0 ) {
581
- $campaigns_notifications = array();
582
- $contact_ids = array();
583
  foreach ( $notifications as $notification ) {
584
  $campaigns_notifications[ $notification['campaign_id'] ][] = $notification;
585
-
586
  $contact_ids[] = $notification['contact_id'];
587
  }
588
-
589
  // We need unique ids
590
  $contact_ids = array_unique( $contact_ids );
591
-
592
  $contacts = ES()->contacts_db->get_details_by_ids( $contact_ids );
593
-
594
  foreach ( $campaigns_notifications as $campaign_id => $notifications ) {
595
-
596
  if ( ! empty( $campaign_id ) ) {
597
  $campaign = ES()->campaigns_db->get( $campaign_id );
598
 
599
  if ( ! empty( $campaign ) ) {
600
-
601
  $content = $campaign['body'];
602
 
603
  $subject = $campaign['subject'];
604
  }
605
  }
606
-
607
  foreach ( $notifications as $notification ) {
608
 
609
  $contact_id = $notification['contact_id'];
@@ -642,7 +640,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
642
  do_action( 'ig_es_message_sent', $contact_id, $campaign_id, 0 );
643
 
644
  $email_sending_limit--;
645
-
646
  // Email Sent now delete from queue now.
647
  $this->db->delete_from_queue( $campaign_id, $contact_id );
648
  }
@@ -715,14 +713,14 @@ if ( ! class_exists( 'ES_Queue' ) ) {
715
  // Try to lock cron job.
716
  $locking_status = $this->lock_cron_job( $cron_job, $cron_job_data );
717
  if ( 'locked' === $locking_status ) {
718
-
719
  register_shutdown_function( array( $this, 'unlock_cron_job' ), $cron_job );
720
-
721
  $campaign_type = '';
722
  if ( ! empty( $campaign_id ) ) {
723
  $campaign_type = ES()->campaigns_db->get_campaign_type_by_id( $campaign_id );
724
  }
725
-
726
  if ( 'newsletter' === $campaign_type ) {
727
  ES()->campaigns_db->update_status( $campaign_id, IG_ES_CAMPAIGN_STATUS_QUEUED );
728
  }
@@ -741,27 +739,27 @@ if ( ! class_exists( 'ES_Queue' ) ) {
741
  // Found Subscribers to send notification?
742
  if ( $total_emails > 0 ) {
743
  $emails = array_column( $emails_data, 'email' );
744
-
745
  $merge_tags = array(
746
  'guid' => $notification_guid,
747
  'message_id' => $message_id,
748
  'campaign_id' => $campaign_id,
749
  );
750
-
751
  $subject = $notification['subject'];
752
  $content = $notification['body'];
753
-
754
- //$content = utf8_encode( $content );
755
  ES()->mailer->send( $subject, $content, $emails, $merge_tags );
756
-
757
  $total_remaining_emails = ES_DB_Sending_Queue::get_total_emails_to_be_sent_by_hash( $notification_guid );
758
  $remaining_emails_to_be_sent = ES_DB_Sending_Queue::get_total_emails_to_be_sent();
759
-
760
  // No emails left for the $notification_guid??? Send admin notification for the
761
  // Completion of a job
762
  if ( 0 == $total_remaining_emails ) {
763
  ES_DB_Mailing_Queue::update_sent_status( $notification_guid, 'Sent' );
764
-
765
  if ( 'newsletter' === $campaign_type ) {
766
  ES()->campaigns_db->update_status( $campaign_id, IG_ES_CAMPAIGN_STATUS_FINISHED );
767
  } elseif ( 'post_digest' === $campaign_type ) {
@@ -772,37 +770,35 @@ if ( ! class_exists( 'ES_Queue' ) ) {
772
  ES()->campaigns_db->update_campaign_meta( $campaign_id, $campaign_meta );
773
  }
774
  }
775
-
776
  // Send Cron Email to admins
777
  ES()->mailer->send_cron_admin_email( $notification_guid );
778
  }
779
-
780
  // TODO: Implement better solution
781
  set_transient( 'ig_es_total_emails_sent', $total_emails, MINUTE_IN_SECONDS );
782
  set_transient( 'ig_es_remaining_email_count', $remaining_emails_to_be_sent, MINUTE_IN_SECONDS );
783
-
784
  $response['total_emails_sent'] = $total_emails;
785
  $response['es_remaining_email_count'] = $remaining_emails_to_be_sent;
786
  $response['message'] = 'EMAILS_SENT';
787
  $response['status'] = 'SUCCESS';
788
  // update last cron run time
789
  update_option( 'ig_es_last_cron_run', time() );
790
-
791
  } else {
792
  $response['es_remaining_email_count'] = 0;
793
  $response['message'] = 'EMAILS_NOT_FOUND';
794
  $response['status'] = 'SUCCESS';
795
  ES_DB_Mailing_Queue::update_sent_status( $notification_guid, 'Sent' );
796
  }
797
-
798
  $this->unlock_cron_job( $cron_job );
799
  }
800
-
801
  } else {
802
  $response['status'] = 'ERROR';
803
  $response['message'] = 'CRON_LOCK_ENABLED';
804
  }
805
-
806
  } else {
807
  $response['es_remaining_email_count'] = 0;
808
  $response['message'] = 'NOTIFICATION_NOT_FOUND';
@@ -840,9 +836,9 @@ if ( ! class_exists( 'ES_Queue' ) ) {
840
  /**
841
  * Delete contact queued emails
842
  *
843
- * @param int $contact_id
844
- * @param int $message_id
845
- * @param int $campaign_id
846
  * @param array $list_ids
847
  *
848
  * @since 4.7.6
@@ -855,26 +851,26 @@ if ( ! class_exists( 'ES_Queue' ) ) {
855
  $contact_ids = array( $contact_ids );
856
  }
857
 
858
- if ( ! empty( $contact_ids ) ) {
859
  foreach ( $contact_ids as $contact_id ) {
860
-
861
  // Queued emails from sending_queue table.
862
  $sending_queue_emails = ES_DB_Sending_Queue::get_queued_emails( $contact_id );
863
-
864
  // Queued emails from queue table.
865
  $where = $wpdb->prepare( 'contact_id = %d AND campaign_id <> 0', $contact_id );
866
  $queued_emails = ES()->queue_db->get_by_conditions( $where );
867
-
868
  // Merge sending queue table emails and queue table emails.
869
  $queued_emails = array_merge( $sending_queue_emails, $queued_emails );
870
-
871
  if ( ! empty( $queued_emails ) ) {
872
  foreach ( $queued_emails as $queued_email ) {
873
  $should_delete = false;
874
  $campaign_id = $queued_email['campaign_id'];
875
  $campaign_list_ids = ES()->campaigns_db->get_list_ids( $campaign_id );
876
  $remaining_list_ids = array_diff( $campaign_list_ids, $list_ids );
877
-
878
  // True when the contact has unsubscribed from all the lists in the campaign.
879
  if ( empty( $remaining_list_ids ) ) {
880
  $should_delete = true;
@@ -886,10 +882,10 @@ if ( ! class_exists( 'ES_Queue' ) ) {
886
  $should_delete = true;
887
  }
888
  }
889
-
890
  if ( $should_delete ) {
891
  // If mailing_queue_id exists then email is from the sending queue table.
892
- if ( ! empty ( $queued_email['mailing_queue_id'] ) ) {
893
  $mailing_queue_id = $queued_email['mailing_queue_id'];
894
  // Delete the contact from the sending queue and update the subscribers count in the mailing queue.
895
  ES_DB_Sending_Queue::delete_contacts( array( $contact_id ), $mailing_queue_id );
@@ -902,7 +898,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
902
  }
903
  }
904
  }
905
-
906
  }
907
 
908
  /**
@@ -966,12 +962,12 @@ if ( ! class_exists( 'ES_Queue' ) ) {
966
  $this->update_email_sent_status( $contact_id, $campaign_id, $message_id, 'In Queue' );
967
  }
968
  }
969
-
970
  /**
971
  * Method to add subscribers to the sending queue in background. Gets called through the Action Scheduler library.
972
  *
973
  * @param array $args action arguements.
974
- *
975
  * @since 4.6.3
976
  */
977
  public function add_subscribers_to_sending_queue( $args = array() ) {
@@ -982,12 +978,12 @@ if ( ! class_exists( 'ES_Queue' ) ) {
982
 
983
  $batch_start_time = time();
984
 
985
- /**
986
- * By subtracting the waiting time from $batch_start_time now,
987
  * We are allowing timeout to happen in the background process loop 3 seconds earlier.
988
- * This earlier timeout will ensure we get engough time to make another asynchrounous request
989
  * since we need to wait for sometime before making the asynchronous request.
990
- **/
991
  $batch_start_time = $batch_start_time - IG_ES_Background_Process_Helper::get_wait_seconds();
992
 
993
  $mailing_queue_id = $args['mailing_queue_id'];
@@ -999,43 +995,43 @@ if ( ! class_exists( 'ES_Queue' ) ) {
999
  if ( empty( $mailing_queue ) ) {
1000
  return false;
1001
  }
1002
-
1003
  $mailing_queue_hash = $mailing_queue['hash'];
1004
  $campaign_id = $mailing_queue['campaign_id'];
1005
-
1006
  $active_subscribers = ES()->contacts_db->get_active_contacts_by_list_and_mailing_queue_id( $list_ids, $mailing_queue_id );
1007
-
1008
  if ( ! empty( $active_subscribers ) ) {
1009
- $subscribers_batch_size = 5000;
1010
-
1011
  // Create batches of subscribers each containing maximum subscribers equal to $subscribers_batch_size.
1012
  $subscribers_batches = array_chunk( $active_subscribers, $subscribers_batch_size );
1013
-
1014
  foreach ( $subscribers_batches as $key => $subscribers ) {
1015
-
1016
  $delivery_data = array();
1017
  $delivery_data['hash'] = $mailing_queue_hash;
1018
  $delivery_data['subscribers'] = $subscribers;
1019
  $delivery_data['campaign_id'] = $campaign_id;
1020
  $delivery_data['mailing_queue_id'] = $mailing_queue_id;
1021
-
1022
  ES_DB_Sending_Queue::do_batch_insert( $delivery_data );
1023
-
1024
  // Remove the processed batch.
1025
  unset( $subscribers_batches[ $key ] );
1026
-
1027
  // Check if time limit or memory limit has been reached.
1028
  if ( IG_ES_Background_Process_Helper::time_exceeded( $batch_start_time ) || IG_ES_Background_Process_Helper::memory_exceeded() ) {
1029
  break;
1030
  }
1031
  }
1032
-
1033
- $total_contacts_added = ES_DB_Sending_Queue::get_total_email_count_by_hash( $mailing_queue_hash );
1034
  ES_DB_Mailing_Queue::update_subscribers_count( $mailing_queue_hash, $total_contacts_added );
1035
-
1036
  // Check if there are no batches to process.
1037
  if ( empty( $subscribers_batches ) ) {
1038
-
1039
  $mailing_queue_status = 'In Queue';
1040
  // Update status to 'In Queue' so that cron(ES Cron/WP Cron) can pick it up.
1041
  ES_DB_Mailing_Queue::update_sent_status( $mailing_queue_hash, $mailing_queue_status );
@@ -1048,10 +1044,10 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1048
  // If campaign_type is newsletter i.e. broadcast, then trigger email sending if its email sending time has come.
1049
  if ( 'newsletter' === $campaign_type ) {
1050
  $queue_start_at = $mailing_queue['start_at'];
1051
-
1052
  $current_timestamp = time();
1053
  $sending_timestamp = strtotime( $queue_start_at );
1054
-
1055
  // Check if campaign sending time has come.
1056
  if ( $sending_timestamp <= $current_timestamp ) {
1057
  $request_args = array(
@@ -1062,12 +1058,11 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1062
  IG_ES_Background_Process_Helper::send_async_ajax_request( $request_args, true );
1063
  }
1064
  }
1065
-
1066
  } else {
1067
  /**
1068
  * If all subscribers batches are not processed(i.e. there are still emails to be added in the sending_queue table)
1069
  * Create another action scheduler task to process remaining batches.
1070
- **/
1071
  $action_args = array(
1072
  'mailing_queue_id' => $mailing_queue_id,
1073
  'list_ids' => $list_ids,
@@ -1075,7 +1070,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1075
  IG_ES_Background_Process_Helper::add_action_scheduler_task( 'ig_es_add_subscribers_to_sending_queue', $action_args, true, true );
1076
  }
1077
  } else {
1078
- $total_contacts_added = ES_DB_Sending_Queue::get_total_email_count_by_hash( $mailing_queue_hash );
1079
  // Check if there are not any queued email for this mailing queue id. If yes, then delete the mailing queue also since there is no meaning in processing an empty mailing queue.
1080
  if ( empty( $total_contacts_added ) ) {
1081
  ES_DB_Mailing_Queue::delete_notifications( array( $mailing_queue_id ) );
@@ -1100,10 +1095,10 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1100
 
1101
  /**
1102
  * Method to set locking options for current cron job
1103
- *
1104
  * @param string $cron_job Job name
1105
- * @param array $cron_job_data Cron job data
1106
- *
1107
  * @since 4.6.4
1108
  */
1109
  public function lock_cron_job( $cron_job = '', $cron_job_data = array() ) {
@@ -1112,7 +1107,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1112
 
1113
  $locking_status = '';
1114
 
1115
- if ( in_array( $cron_job, $es_cron_jobs, true ) ) {
1116
 
1117
  $locked_cron_job_data = get_option( $cron_job . '_locked_data', false );
1118
  if ( ! empty( $locked_cron_job_data ) ) {
@@ -1120,16 +1115,15 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1120
  } else {
1121
  $locked_cron_job_data = array(
1122
  'locked_at' => time(),
1123
- 'data' => $cron_job_data
1124
  );
1125
- $job_locked = update_option( $cron_job . '_locked_data', $locked_cron_job_data , false );
1126
  if ( $job_locked ) {
1127
  $locking_status = 'locked';
1128
  } else {
1129
  $locking_status = 'failed';
1130
  }
1131
  }
1132
-
1133
  }
1134
 
1135
  return $locking_status;
@@ -1137,11 +1131,11 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1137
 
1138
  /**
1139
  * Method to set locking options for current cron job
1140
- *
1141
  * @param string $cron_job Cron Job name.
1142
- *
1143
  * @return bool $cron_job_locked Is cron job locked.
1144
- *
1145
  * @since 4.6.4
1146
  */
1147
  public function is_cron_job_locked( $cron_job = '' ) {
@@ -1150,7 +1144,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1150
 
1151
  $cron_job_locked = false;
1152
 
1153
- if ( in_array( $cron_job, $es_cron_jobs, true ) ) {
1154
 
1155
  $locked_cron_job_data = get_option( $cron_job . '_locked_data', false );
1156
  if ( ! empty( $locked_cron_job_data ) ) {
@@ -1163,11 +1157,11 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1163
 
1164
  /**
1165
  * Method to delete locking options for current cron job
1166
- *
1167
  * @param string $cron_job Job name
1168
-
1169
  * @return string $unlocking_status Cron job unlocking status
1170
- *
1171
  * @since 4.6.4
1172
  */
1173
  public function unlock_cron_job( $cron_job = '' ) {
@@ -1176,7 +1170,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1176
 
1177
  $unlocking_status = '';
1178
 
1179
- if ( in_array( $cron_job, $es_cron_jobs, true ) ) {
1180
  $job_unlocked = delete_option( $cron_job . '_locked_data' );
1181
  if ( $job_unlocked ) {
1182
  $unlocking_status = 'unlocked';
@@ -1192,7 +1186,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1192
  * Should Unlock Cron?
1193
  *
1194
  * @param string $cron_job Cron job name
1195
- * @param bool $force Should unlock the cron job forcefully.
1196
  *
1197
  * @return bool $should_unlock Should unlock the cron.
1198
  *
@@ -1204,7 +1198,7 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1204
 
1205
  $es_cron_jobs = ES()->cron->get_cron_jobs_list();
1206
 
1207
- if ( in_array( $cron_job, $es_cron_jobs, true ) ) {
1208
 
1209
  if ( $force ) {
1210
  $should_unlock = true;
@@ -1212,9 +1206,9 @@ if ( ! class_exists( 'ES_Queue' ) ) {
1212
  $locked_cron_job_data = get_option( $cron_job . '_locked_data', false );
1213
  if ( ! empty( $locked_cron_job_data ) ) {
1214
  $locked_at = $locked_cron_job_data['locked_at'];
1215
-
1216
  $time_lapsed = time() - $locked_at;
1217
-
1218
  // Since maximum allowed cron execution duration is always equal to the set cron interval, check if time lapsed is more than the cron interval.
1219
  $should_unlock = $time_lapsed > ES()->cron->get_cron_interval();
1220
  }
43
  add_action( 'ig_es_message_sent', array( &$this, 'update_email_sent_count' ), 10, 3 );
44
  add_action( 'ig_es_contact_unsubscribe', array( &$this, 'delete_contact_queued_emails' ), 10, 4 );
45
  add_action( 'ig_es_admin_contact_unsubscribe', array( &$this, 'delete_contact_queued_emails' ), 10, 4 );
46
+
47
  // Action scheduler action to add subscribers to sending_queue table in background. Called through Action Scheduler library.
48
  add_action( 'ig_es_add_subscribers_to_sending_queue', array( &$this, 'add_subscribers_to_sending_queue' ) );
49
+
50
  // Ajax handler for running action scheduler task.
51
  add_action( 'wp_ajax_ig_es_run_action_scheduler_task', array( 'IG_ES_Background_Process_Helper', 'run_action_scheduler_task' ) );
52
  add_action( 'wp_ajax_nopriv_ig_es_run_action_scheduler_task', array( 'IG_ES_Background_Process_Helper', 'run_action_scheduler_task' ) );
53
+
54
  // Ajax handler for triggering email queue sending.
55
  add_action( 'wp_ajax_ig_es_trigger_mailing_queue_sending', array( $this, 'trigger_mailing_queue_sending' ) );
56
  add_action( 'wp_ajax_nopriv_ig_es_trigger_mailing_queue_sending', array( $this, 'trigger_mailing_queue_sending' ) );
170
  if ( is_array( $result ) ) {
171
 
172
  $mailing_queue_id = $result['id'];
173
+
174
  if ( ! empty( $mailing_queue_id ) ) {
175
  $mailing_queue_hash = $result['hash'];
176
  ES_DB_Sending_Queue::do_insert_from_contacts_table( $mailing_queue_id, $mailing_queue_hash, $campaign_id, $list_id );
282
  $list_ids = $campaign['list_ids'];
283
 
284
  $campaign = ES()->campaigns_db->get( $campaign_id );
285
+
286
  $conditions = array();
287
  if ( ! empty( $campaign ) && ! empty( $campaign['meta'] ) ) {
288
  $campaign_meta = maybe_unserialize( $campaign['meta'] );
293
 
294
  $conditions = ! empty( $meta['list_conditions'] ) ? $meta['list_conditions'] : array();
295
 
 
296
  $query_args = array(
297
+ 'select' => array(
298
  'lists_subscribers.contact_id AS contact_id',
299
  "UNIX_TIMESTAMP ( lists_subscribers.subscribed_at + INTERVAL $offset ) AS timestamp",
300
  ),
301
  'sent__not_in' => array( $campaign_id ),
302
  'queue__not_in' => array( $campaign_id ),
303
+ 'lists' => $list_ids,
304
+ 'conditions' => $conditions,
305
+ 'having' => array( 'timestamp <= ' . ( $now + $queue_upfront ) ),
306
+ 'orderby' => array( 'timestamp' ),
307
+ 'groupby' => 'lists_subscribers.contact_id',
308
  );
309
 
310
  if ( $grace_period ) {
318
  // ES()->logger->info( $query );
319
  // ES()->logger->info( '----------------------------Query Args Complete (ig_es_contact_insert) ----------------------------' );
320
 
 
321
  // ES()->logger->info( 'Results: ' . print_r( $results, true ) );
322
 
323
  if ( ! empty( $results ) ) {
542
  * @since 4.2.1
543
  */
544
  public function process_queue() {
545
+
546
  global $wpdb;
547
 
548
  if ( ES()->cron->should_unlock() ) {
550
  }
551
 
552
  ES()->cron->set_last_hit();
553
+
554
  $email_sending_limit = ES()->mailer->get_total_emails_send_now();
555
 
556
  if ( $email_sending_limit > 0 ) {
557
 
558
  $micro_time = microtime( true );
559
+
560
  // ES()->logger->info( 'Process Queue:' );
561
  // ES()->logger->info( 'SQL: ' . $sql );
562
+
563
+ $notifications = $wpdb->get_results(
564
  $wpdb->prepare(
565
  "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
566
  FROM {$wpdb->prefix}ig_queue AS queue
568
  WHERE queue.timestamp <= %d AND queue.sent_at = 0
569
  AND (campaigns.status = 1 OR queue.ignore_status = 1)
570
  ORDER BY queue.priority DESC",
571
+ (int) $micro_time
572
  ),
573
  ARRAY_A
574
  );
575
+
576
  $batch_start_time = time();
577
+
578
  if ( is_array( $notifications ) && count( $notifications ) > 0 ) {
579
+ $campaigns_notifications = array();
580
+ $contact_ids = array();
581
  foreach ( $notifications as $notification ) {
582
  $campaigns_notifications[ $notification['campaign_id'] ][] = $notification;
583
+
584
  $contact_ids[] = $notification['contact_id'];
585
  }
586
+
587
  // We need unique ids
588
  $contact_ids = array_unique( $contact_ids );
589
+
590
  $contacts = ES()->contacts_db->get_details_by_ids( $contact_ids );
591
+
592
  foreach ( $campaigns_notifications as $campaign_id => $notifications ) {
593
+
594
  if ( ! empty( $campaign_id ) ) {
595
  $campaign = ES()->campaigns_db->get( $campaign_id );
596
 
597
  if ( ! empty( $campaign ) ) {
598
+
599
  $content = $campaign['body'];
600
 
601
  $subject = $campaign['subject'];
602
  }
603
  }
604
+
605
  foreach ( $notifications as $notification ) {
606
 
607
  $contact_id = $notification['contact_id'];
640
  do_action( 'ig_es_message_sent', $contact_id, $campaign_id, 0 );
641
 
642
  $email_sending_limit--;
643
+
644
  // Email Sent now delete from queue now.
645
  $this->db->delete_from_queue( $campaign_id, $contact_id );
646
  }
713
  // Try to lock cron job.
714
  $locking_status = $this->lock_cron_job( $cron_job, $cron_job_data );
715
  if ( 'locked' === $locking_status ) {
716
+
717
  register_shutdown_function( array( $this, 'unlock_cron_job' ), $cron_job );
718
+
719
  $campaign_type = '';
720
  if ( ! empty( $campaign_id ) ) {
721
  $campaign_type = ES()->campaigns_db->get_campaign_type_by_id( $campaign_id );
722
  }
723
+
724
  if ( 'newsletter' === $campaign_type ) {
725
  ES()->campaigns_db->update_status( $campaign_id, IG_ES_CAMPAIGN_STATUS_QUEUED );
726
  }
739
  // Found Subscribers to send notification?
740
  if ( $total_emails > 0 ) {
741
  $emails = array_column( $emails_data, 'email' );
742
+
743
  $merge_tags = array(
744
  'guid' => $notification_guid,
745
  'message_id' => $message_id,
746
  'campaign_id' => $campaign_id,
747
  );
748
+
749
  $subject = $notification['subject'];
750
  $content = $notification['body'];
751
+
752
+ // $content = utf8_encode( $content );
753
  ES()->mailer->send( $subject, $content, $emails, $merge_tags );
754
+
755
  $total_remaining_emails = ES_DB_Sending_Queue::get_total_emails_to_be_sent_by_hash( $notification_guid );
756
  $remaining_emails_to_be_sent = ES_DB_Sending_Queue::get_total_emails_to_be_sent();
757
+
758
  // No emails left for the $notification_guid??? Send admin notification for the
759
  // Completion of a job
760
  if ( 0 == $total_remaining_emails ) {
761
  ES_DB_Mailing_Queue::update_sent_status( $notification_guid, 'Sent' );
762
+
763
  if ( 'newsletter' === $campaign_type ) {
764
  ES()->campaigns_db->update_status( $campaign_id, IG_ES_CAMPAIGN_STATUS_FINISHED );
765
  } elseif ( 'post_digest' === $campaign_type ) {
770
  ES()->campaigns_db->update_campaign_meta( $campaign_id, $campaign_meta );
771
  }
772
  }
773
+
774
  // Send Cron Email to admins
775
  ES()->mailer->send_cron_admin_email( $notification_guid );
776
  }
777
+
778
  // TODO: Implement better solution
779
  set_transient( 'ig_es_total_emails_sent', $total_emails, MINUTE_IN_SECONDS );
780
  set_transient( 'ig_es_remaining_email_count', $remaining_emails_to_be_sent, MINUTE_IN_SECONDS );
781
+
782
  $response['total_emails_sent'] = $total_emails;
783
  $response['es_remaining_email_count'] = $remaining_emails_to_be_sent;
784
  $response['message'] = 'EMAILS_SENT';
785
  $response['status'] = 'SUCCESS';
786
  // update last cron run time
787
  update_option( 'ig_es_last_cron_run', time() );
788
+
789
  } else {
790
  $response['es_remaining_email_count'] = 0;
791
  $response['message'] = 'EMAILS_NOT_FOUND';
792
  $response['status'] = 'SUCCESS';
793
  ES_DB_Mailing_Queue::update_sent_status( $notification_guid, 'Sent' );
794
  }
795
+
796
  $this->unlock_cron_job( $cron_job );
797
  }
 
798
  } else {
799
  $response['status'] = 'ERROR';
800
  $response['message'] = 'CRON_LOCK_ENABLED';
801
  }
 
802
  } else {
803
  $response['es_remaining_email_count'] = 0;
804
  $response['message'] = 'NOTIFICATION_NOT_FOUND';
836
  /**
837
  * Delete contact queued emails
838
  *
839
+ * @param int $contact_id
840
+ * @param int $message_id
841
+ * @param int $campaign_id
842
  * @param array $list_ids
843
  *
844
  * @since 4.7.6
851
  $contact_ids = array( $contact_ids );
852
  }
853
 
854
+ if ( ! empty( $contact_ids ) ) {
855
  foreach ( $contact_ids as $contact_id ) {
856
+
857
  // Queued emails from sending_queue table.
858
  $sending_queue_emails = ES_DB_Sending_Queue::get_queued_emails( $contact_id );
859
+
860
  // Queued emails from queue table.
861
  $where = $wpdb->prepare( 'contact_id = %d AND campaign_id <> 0', $contact_id );
862
  $queued_emails = ES()->queue_db->get_by_conditions( $where );
863
+
864
  // Merge sending queue table emails and queue table emails.
865
  $queued_emails = array_merge( $sending_queue_emails, $queued_emails );
866
+
867
  if ( ! empty( $queued_emails ) ) {
868
  foreach ( $queued_emails as $queued_email ) {
869
  $should_delete = false;
870
  $campaign_id = $queued_email['campaign_id'];
871
  $campaign_list_ids = ES()->campaigns_db->get_list_ids( $campaign_id );
872
  $remaining_list_ids = array_diff( $campaign_list_ids, $list_ids );
873
+
874
  // True when the contact has unsubscribed from all the lists in the campaign.
875
  if ( empty( $remaining_list_ids ) ) {
876
  $should_delete = true;
882
  $should_delete = true;
883
  }
884
  }
885
+
886
  if ( $should_delete ) {
887
  // If mailing_queue_id exists then email is from the sending queue table.
888
+ if ( ! empty( $queued_email['mailing_queue_id'] ) ) {
889
  $mailing_queue_id = $queued_email['mailing_queue_id'];
890
  // Delete the contact from the sending queue and update the subscribers count in the mailing queue.
891
  ES_DB_Sending_Queue::delete_contacts( array( $contact_id ), $mailing_queue_id );
898
  }
899
  }
900
  }
901
+
902
  }
903
 
904
  /**
962
  $this->update_email_sent_status( $contact_id, $campaign_id, $message_id, 'In Queue' );
963
  }
964
  }
965
+
966
  /**
967
  * Method to add subscribers to the sending queue in background. Gets called through the Action Scheduler library.
968
  *
969
  * @param array $args action arguements.
970
+ *
971
  * @since 4.6.3
972
  */
973
  public function add_subscribers_to_sending_queue( $args = array() ) {
978
 
979
  $batch_start_time = time();
980
 
981
+ /**
982
+ * By subtracting the waiting time from $batch_start_time now,
983
  * We are allowing timeout to happen in the background process loop 3 seconds earlier.
984
+ * This earlier timeout will ensure we get engough time to make another asynchrounous request
985
  * since we need to wait for sometime before making the asynchronous request.
986
+ */
987
  $batch_start_time = $batch_start_time - IG_ES_Background_Process_Helper::get_wait_seconds();
988
 
989
  $mailing_queue_id = $args['mailing_queue_id'];
995
  if ( empty( $mailing_queue ) ) {
996
  return false;
997
  }
998
+
999
  $mailing_queue_hash = $mailing_queue['hash'];
1000
  $campaign_id = $mailing_queue['campaign_id'];
1001
+
1002
  $active_subscribers = ES()->contacts_db->get_active_contacts_by_list_and_mailing_queue_id( $list_ids, $mailing_queue_id );
1003
+
1004
  if ( ! empty( $active_subscribers ) ) {
1005
+ $subscribers_batch_size = 5000;
1006
+
1007
  // Create batches of subscribers each containing maximum subscribers equal to $subscribers_batch_size.
1008
  $subscribers_batches = array_chunk( $active_subscribers, $subscribers_batch_size );
1009
+
1010
  foreach ( $subscribers_batches as $key => $subscribers ) {
1011
+
1012
  $delivery_data = array();
1013
  $delivery_data['hash'] = $mailing_queue_hash;
1014
  $delivery_data['subscribers'] = $subscribers;
1015
  $delivery_data['campaign_id'] = $campaign_id;
1016
  $delivery_data['mailing_queue_id'] = $mailing_queue_id;
1017
+
1018
  ES_DB_Sending_Queue::do_batch_insert( $delivery_data );
1019
+
1020
  // Remove the processed batch.
1021
  unset( $subscribers_batches[ $key ] );
1022
+
1023
  // Check if time limit or memory limit has been reached.
1024
  if ( IG_ES_Background_Process_Helper::time_exceeded( $batch_start_time ) || IG_ES_Background_Process_Helper::memory_exceeded() ) {
1025
  break;
1026
  }
1027
  }
1028
+
1029
+ $total_contacts_added = ES_DB_Sending_Queue::get_total_email_count_by_hash( $mailing_queue_hash );
1030
  ES_DB_Mailing_Queue::update_subscribers_count( $mailing_queue_hash, $total_contacts_added );
1031
+
1032
  // Check if there are no batches to process.
1033
  if ( empty( $subscribers_batches ) ) {
1034
+
1035
  $mailing_queue_status = 'In Queue';
1036
  // Update status to 'In Queue' so that cron(ES Cron/WP Cron) can pick it up.
1037
  ES_DB_Mailing_Queue::update_sent_status( $mailing_queue_hash, $mailing_queue_status );
1044
  // If campaign_type is newsletter i.e. broadcast, then trigger email sending if its email sending time has come.
1045
  if ( 'newsletter' === $campaign_type ) {
1046
  $queue_start_at = $mailing_queue['start_at'];
1047
+
1048
  $current_timestamp = time();
1049
  $sending_timestamp = strtotime( $queue_start_at );
1050
+
1051
  // Check if campaign sending time has come.
1052
  if ( $sending_timestamp <= $current_timestamp ) {
1053
  $request_args = array(
1058
  IG_ES_Background_Process_Helper::send_async_ajax_request( $request_args, true );
1059
  }
1060
  }
 
1061
  } else {
1062
  /**
1063
  * If all subscribers batches are not processed(i.e. there are still emails to be added in the sending_queue table)
1064
  * Create another action scheduler task to process remaining batches.
1065
+ */
1066
  $action_args = array(
1067
  'mailing_queue_id' => $mailing_queue_id,
1068
  'list_ids' => $list_ids,
1070
  IG_ES_Background_Process_Helper::add_action_scheduler_task( 'ig_es_add_subscribers_to_sending_queue', $action_args, true, true );
1071
  }
1072
  } else {
1073
+ $total_contacts_added = ES_DB_Sending_Queue::get_total_email_count_by_hash( $mailing_queue_hash );
1074
  // Check if there are not any queued email for this mailing queue id. If yes, then delete the mailing queue also since there is no meaning in processing an empty mailing queue.
1075
  if ( empty( $total_contacts_added ) ) {
1076
  ES_DB_Mailing_Queue::delete_notifications( array( $mailing_queue_id ) );
1095
 
1096
  /**
1097
  * Method to set locking options for current cron job
1098
+ *
1099
  * @param string $cron_job Job name
1100
+ * @param array $cron_job_data Cron job data
1101
+ *
1102
  * @since 4.6.4
1103
  */
1104
  public function lock_cron_job( $cron_job = '', $cron_job_data = array() ) {
1107
 
1108
  $locking_status = '';
1109
 
1110
+ if ( in_array( $cron_job, $es_cron_jobs, true ) ) {
1111
 
1112
  $locked_cron_job_data = get_option( $cron_job . '_locked_data', false );
1113
  if ( ! empty( $locked_cron_job_data ) ) {
1115
  } else {
1116
  $locked_cron_job_data = array(
1117
  'locked_at' => time(),
1118
+ 'data' => $cron_job_data,
1119
  );
1120
+ $job_locked = update_option( $cron_job . '_locked_data', $locked_cron_job_data, false );
1121
  if ( $job_locked ) {
1122
  $locking_status = 'locked';
1123
  } else {
1124
  $locking_status = 'failed';
1125
  }
1126
  }
 
1127
  }
1128
 
1129
  return $locking_status;
1131
 
1132
  /**
1133
  * Method to set locking options for current cron job
1134
+ *
1135
  * @param string $cron_job Cron Job name.
1136
+ *
1137
  * @return bool $cron_job_locked Is cron job locked.
1138
+ *
1139
  * @since 4.6.4
1140
  */
1141
  public function is_cron_job_locked( $cron_job = '' ) {
1144
 
1145
  $cron_job_locked = false;
1146
 
1147
+ if ( in_array( $cron_job, $es_cron_jobs, true ) ) {
1148
 
1149
  $locked_cron_job_data = get_option( $cron_job . '_locked_data', false );
1150
  if ( ! empty( $locked_cron_job_data ) ) {
1157
 
1158
  /**
1159
  * Method to delete locking options for current cron job
1160
+ *
1161
  * @param string $cron_job Job name
1162
+
1163
  * @return string $unlocking_status Cron job unlocking status
1164
+ *
1165
  * @since 4.6.4
1166
  */
1167
  public function unlock_cron_job( $cron_job = '' ) {
1170
 
1171
  $unlocking_status = '';
1172
 
1173
+ if ( in_array( $cron_job, $es_cron_jobs, true ) ) {
1174
  $job_unlocked = delete_option( $cron_job . '_locked_data' );
1175
  if ( $job_unlocked ) {
1176
  $unlocking_status = 'unlocked';
1186
  * Should Unlock Cron?
1187
  *
1188
  * @param string $cron_job Cron job name
1189
+ * @param bool $force Should unlock the cron job forcefully.
1190
  *
1191
  * @return bool $should_unlock Should unlock the cron.
1192
  *
1198
 
1199
  $es_cron_jobs = ES()->cron->get_cron_jobs_list();
1200
 
1201
+ if ( in_array( $cron_job, $es_cron_jobs, true ) ) {
1202
 
1203
  if ( $force ) {
1204
  $should_unlock = true;
1206
  $locked_cron_job_data = get_option( $cron_job . '_locked_data', false );
1207
  if ( ! empty( $locked_cron_job_data ) ) {
1208
  $locked_at = $locked_cron_job_data['locked_at'];
1209
+
1210
  $time_lapsed = time() - $locked_at;
1211
+
1212
  // Since maximum allowed cron execution duration is always equal to the set cron interval, check if time lapsed is more than the cron interval.
1213
  $should_unlock = $time_lapsed > ES()->cron->get_cron_interval();
1214
  }
lite/includes/classes/class-es-reports-data.php CHANGED
@@ -173,7 +173,7 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
173
  }
174
  if ( $last_week_total_contacts <= 0 && $this_week_total_contacts <= 0 ) {
175
  return 0;
176
- } else if ( $last_week_total_contacts <= 0 && $this_week_total_contacts > 0 ) {
177
  return 100;
178
  } else {
179
  return ( $this_week_total_contacts - $last_week_total_contacts ) / $last_week_total_contacts * 100;
@@ -210,20 +210,20 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
210
  }
211
  }
212
 
213
- $total_contacts = self::get_total_contacts();
214
- $total_forms = ES()->forms_db->count_forms();
215
- $total_lists = ES()->lists_db->count_lists();
216
- $total_campaigns = ES()->campaigns_db->get_total_campaigns();
217
  $total_contacts_subscribed = self::get_total_subscribed_contacts( $days );
218
-
219
  $total_email_opens = self::get_total_contacts_opened_emails( $days, false );
220
  $total_links_clicks = self::get_total_contacts_clicks_links( $days, false );
221
  $total_message_sent = self::get_total_emails_sent( $days, false );
222
  $total_contact_lost = self::get_total_unsubscribed_contacts( $days );
223
- $contacts_growth = self::get_contacts_growth();
224
 
225
  $total_open_rate = 0;
226
- $total_click_rate = 0;
227
  $total_lost_rate = 0;
228
  if ( $total_message_sent > 0 ) {
229
  $total_open_rate = ( $total_email_opens ) / $total_message_sent;
@@ -247,7 +247,6 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
247
 
248
  $data = array();
249
 
250
-
251
  $can_show = self::can_show_campaign_stats( $source );
252
  if ( $can_show ) {
253
 
@@ -255,20 +254,20 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
255
  }
256
 
257
  $reports_data = array(
258
- 'total_contacts' => number_format( $total_contacts ),
259
- 'total_lists' => number_format( $total_lists ),
260
- 'total_forms' => number_format( $total_forms ),
261
- 'total_campaigns' => number_format( $total_campaigns ),
262
  'total_contacts_subscribed' => number_format( $total_contacts_subscribed ),
263
- 'total_email_opens' => number_format( $total_email_opens ),
264
- 'total_message_sent' => number_format( $total_message_sent ),
265
- 'total_contact_lost' => number_format( $total_contact_lost ),
266
- 'avg_open_rate' => number_format( $avg_open_rate, 2 ),
267
- 'avg_click_rate' => number_format( $avg_click_rate, 2 ),
268
- 'total_open_rate' => number_format( $total_open_rate, 2 ),
269
- 'total_click_rate' => $total_click_rate,
270
- 'total_lost_rate' => $total_lost_rate,
271
- 'contacts_growth' => $contacts_growth,
272
  );
273
 
274
  $data = array_merge( $data, $reports_data );
@@ -304,11 +303,11 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
304
  }
305
 
306
  $results = $wpdb->get_results( $wpdb->prepare( "SELECT type, count(DISTINCT (contact_id) ) as total FROM {$wpdb->prefix}ig_actions WHERE message_id = %d AND campaign_id = %d GROUP BY type", $message_id, $campaign_id ), ARRAY_A );
307
-
308
  $stats = array();
309
  $type = '';
310
  $type_text = '';
311
-
312
  if ( count( $results ) > 0 ) {
313
 
314
  foreach ( $results as $result ) {
@@ -335,7 +334,15 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
335
  }
336
  }
337
 
338
- $stats = wp_parse_args( $stats, array( 'total_sent' => 0, 'total_opens' => 0, 'total_clicks' => 0, 'total_unsubscribe' => 0 ) );
 
 
 
 
 
 
 
 
339
 
340
  if ( 0 != $stats['total_sent'] ) {
341
  $campaign_opens_rate = ( $stats['total_opens'] * 100 ) / $stats['total_sent'];
@@ -372,10 +379,9 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
372
  $campaigns_data[ $key ]['start_at'] = $start_at;
373
  $campaigns_data[ $key ]['finish_at'] = $finish_at;
374
  }
375
-
376
  }
377
  $data['campaigns'] = $campaigns_data;
378
-
379
  return $data;
380
  }
381
 
173
  }
174
  if ( $last_week_total_contacts <= 0 && $this_week_total_contacts <= 0 ) {
175
  return 0;
176
+ } elseif ( $last_week_total_contacts <= 0 && $this_week_total_contacts > 0 ) {
177
  return 100;
178
  } else {
179
  return ( $this_week_total_contacts - $last_week_total_contacts ) / $last_week_total_contacts * 100;
210
  }
211
  }
212
 
213
+ $total_contacts = self::get_total_contacts();
214
+ $total_forms = ES()->forms_db->count_forms();
215
+ $total_lists = ES()->lists_db->count_lists();
216
+ $total_campaigns = ES()->campaigns_db->get_total_campaigns();
217
  $total_contacts_subscribed = self::get_total_subscribed_contacts( $days );
218
+
219
  $total_email_opens = self::get_total_contacts_opened_emails( $days, false );
220
  $total_links_clicks = self::get_total_contacts_clicks_links( $days, false );
221
  $total_message_sent = self::get_total_emails_sent( $days, false );
222
  $total_contact_lost = self::get_total_unsubscribed_contacts( $days );
223
+ $contacts_growth = self::get_contacts_growth();
224
 
225
  $total_open_rate = 0;
226
+ $total_click_rate = 0;
227
  $total_lost_rate = 0;
228
  if ( $total_message_sent > 0 ) {
229
  $total_open_rate = ( $total_email_opens ) / $total_message_sent;
247
 
248
  $data = array();
249
 
 
250
  $can_show = self::can_show_campaign_stats( $source );
251
  if ( $can_show ) {
252
 
254
  }
255
 
256
  $reports_data = array(
257
+ 'total_contacts' => number_format( $total_contacts ),
258
+ 'total_lists' => number_format( $total_lists ),
259
+ 'total_forms' => number_format( $total_forms ),
260
+ 'total_campaigns' => number_format( $total_campaigns ),
261
  'total_contacts_subscribed' => number_format( $total_contacts_subscribed ),
262
+ 'total_email_opens' => number_format( $total_email_opens ),
263
+ 'total_message_sent' => number_format( $total_message_sent ),
264
+ 'total_contact_lost' => number_format( $total_contact_lost ),
265
+ 'avg_open_rate' => number_format( $avg_open_rate, 2 ),
266
+ 'avg_click_rate' => number_format( $avg_click_rate, 2 ),
267
+ 'total_open_rate' => number_format( $total_open_rate, 2 ),
268
+ 'total_click_rate' => $total_click_rate,
269
+ 'total_lost_rate' => $total_lost_rate,
270
+ 'contacts_growth' => $contacts_growth,
271
  );
272
 
273
  $data = array_merge( $data, $reports_data );
303
  }
304
 
305
  $results = $wpdb->get_results( $wpdb->prepare( "SELECT type, count(DISTINCT (contact_id) ) as total FROM {$wpdb->prefix}ig_actions WHERE message_id = %d AND campaign_id = %d GROUP BY type", $message_id, $campaign_id ), ARRAY_A );
306
+
307
  $stats = array();
308
  $type = '';
309
  $type_text = '';
310
+
311
  if ( count( $results ) > 0 ) {
312
 
313
  foreach ( $results as $result ) {
334
  }
335
  }
336
 
337
+ $stats = wp_parse_args(
338
+ $stats,
339
+ array(
340
+ 'total_sent' => 0,
341
+ 'total_opens' => 0,
342
+ 'total_clicks' => 0,
343
+ 'total_unsubscribe' => 0,
344
+ )
345
+ );
346
 
347
  if ( 0 != $stats['total_sent'] ) {
348
  $campaign_opens_rate = ( $stats['total_opens'] * 100 ) / $stats['total_sent'];
379
  $campaigns_data[ $key ]['start_at'] = $start_at;
380
  $campaigns_data[ $key ]['finish_at'] = $finish_at;
381
  }
 
382
  }
383
  $data['campaigns'] = $campaigns_data;
384
+
385
  return $data;
386
  }
387
 
lite/includes/classes/class-es-reports-table.php CHANGED
@@ -20,7 +20,6 @@ class ES_Reports_Table extends ES_List_Table {
20
  )
21
  );
22
 
23
-
24
  add_action( 'admin_footer', array( $this, 'display_preview_email' ), 10 );
25
  }
26
 
@@ -28,14 +27,14 @@ class ES_Reports_Table extends ES_List_Table {
28
 
29
  $campaign_id = ig_es_get_request_data( 'campaign_id' );
30
  $campaign_type = '';
31
- //Since, currently we are not passing campaign_id with broadcast $campaign_type will remain empty for broadcast
32
- if ( ! empty ( $campaign_id ) ) {
33
  $campaign_type = ES()->campaigns_db->get_campaign_type_by_id( $campaign_id );
34
  }
35
 
36
  $campaign_types = array( 'sequence', 'sequence_message' );
37
- //Only if it is sequence then control will transfer to Sequence Reports class.
38
- if ( ! empty ( $campaign_type ) && in_array( $campaign_type, $campaign_types, true ) ) {
39
  if ( ES()->is_pro() ) {
40
  $reports = ES_Pro_Sequence_Reports::get_instance();
41
  $reports->es_sequence_reports_callback();
@@ -63,7 +62,7 @@ class ES_Reports_Table extends ES_List_Table {
63
  /* translators: %s: Cron url */
64
  $content = '<a href="' . esc_url( $cron_url ) . '" class="px-3 py-2 ig-es-imp-button">' . esc_html__( 'Send Queued Emails Now', 'email-subscribers' ) . '</a>';
65
  } else {
66
- $content = '<span class="ig-es-send-queue-emails px-3 button-disabled">' . esc_html__( 'Send Queued Emails Now', 'email-subscribers' ) . '</span>';
67
  $content .= '<br /><span class="es-helper pl-6">' . esc_html__( 'No emails found in queue', 'email-subscribers' ) . '</span>';
68
  }
69
  ?>
@@ -104,7 +103,6 @@ class ES_Reports_Table extends ES_List_Table {
104
  }
105
  }
106
 
107
-
108
  }
109
 
110
  public function screen_option() {
@@ -118,7 +116,7 @@ class ES_Reports_Table extends ES_List_Table {
118
 
119
  add_screen_option( $option, $args );
120
 
121
- }
122
 
123
  /** Text displayed when no list data is available */
124
  public function no_items() {
@@ -128,7 +126,7 @@ class ES_Reports_Table extends ES_List_Table {
128
  /**
129
  * Generates content for a single row of the table.
130
  * Overrides WP_List_Table class single_row function.
131
- *
132
  * @since 4.7.8
133
  *
134
  * @param object|array $item The current item
@@ -142,7 +140,7 @@ class ES_Reports_Table extends ES_List_Table {
142
  /**
143
  * Render a column when no column specific method exist.
144
  *
145
- * @param array $item
146
  * @param string $column_name
147
  *
148
  * @return mixed
@@ -185,30 +183,42 @@ class ES_Reports_Table extends ES_List_Table {
185
  $report_status = $item['status'];
186
  $status_html = '';
187
  if ( IG_ES_MAILING_QUEUE_STATUS_SENT === $report_status ) {
188
- $status_html = sprintf( '<svg class="flex-shrink-0 h-6 w-6 text-green-400" fill="currentColor" viewBox="0 0 20 20">
 
189
  <title>%s</title>
190
  <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
191
- </svg>', __( 'Sent', 'email-subscribers' ) );
 
 
192
  } else {
193
  if ( IG_ES_MAILING_QUEUE_STATUS_SENDING === $report_status ) {
194
- $status_html = sprintf( '<svg class="flex-shrink-0 h-6 w-6 text-yellow-400 inline" fill="currentColor" viewBox="0 0 20 20">
 
195
  <title>%s</title>
196
  <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-8.707l-3-3a1 1 0 00-1.414 1.414L10.586 9H7a1 1 0 100 2h3.586l-1.293 1.293a1 1 0 101.414 1.414l3-3a1 1 0 000-1.414z" clip-rule="evenodd"/>
197
- </svg>', __( 'Sending', 'email-subscribers' ) );
 
 
198
  } elseif ( IG_ES_MAILING_QUEUE_STATUS_PAUSED === $report_status ) {
199
- $status_html = sprintf( '<svg xmlns="http://www.w3.org/2000/svg" class="flex-shrink-0 h-6 w-6 inline text-gray-500" viewBox="0 0 20 20" fill="currentColor">
 
200
  <title>%s</title>
201
  <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
202
- </svg>', __( 'Paused', 'email-subscribers' ) );
 
 
203
  } elseif ( IG_ES_MAILING_QUEUE_STATUS_QUEUED === $report_status ) {
204
- $status_html = sprintf( '<svg class="flex-shrink-0 h-6 w-6 inline text-orange-400" fill="currentColor" viewBox="0 0 20 20">
 
205
  <title>%s</title>
206
  <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"/>
207
- </svg>', __( 'Scheduled', 'email-subscribers' ) );
 
 
208
  }
209
  $actions = array();
210
  if ( in_array( $report_status, array( IG_ES_MAILING_QUEUE_STATUS_QUEUED, IG_ES_MAILING_QUEUE_STATUS_SENDING ), true ) ) {
211
- $actions[ 'send_now' ] = $this->prepare_send_now_url( $item );
212
  }
213
 
214
  $actions = apply_filters( 'ig_es_report_row_actions', $actions, $item );
@@ -265,14 +275,14 @@ class ES_Reports_Table extends ES_List_Table {
265
  */
266
  public function get_columns() {
267
  $columns = array(
268
- 'cb' => '<input type="checkbox" />',
269
- 'subject' => __( 'Subject', 'email-subscribers' ),
270
- 'type' => __( 'Type', 'email-subscribers' ),
271
- 'status' => __( 'Status', 'email-subscribers' ),
272
- 'start_at' => __( 'Start Date', 'email-subscribers' ),
273
- 'finish_at' => __( 'End Date', 'email-subscribers' ),
274
- 'count' => __( 'Total contacts', 'email-subscribers' ),
275
- 'total_sent' => __( 'Total sent', 'email-subscribers' ),
276
  );
277
 
278
  return $columns;
@@ -305,11 +315,15 @@ class ES_Reports_Table extends ES_List_Table {
305
  $content = '';
306
  if ( ! empty( $cron_url ) ) {
307
  /* translators: %s: Cron url */
308
- $content = sprintf( '<a href="%s" target="_blank">
 
309
  <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 inline text-yellow-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
310
  <title>%s</title>
311
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z" />
312
- </svg></a>', $cron_url , __( 'Send now', 'email-subscribers' ) );
 
 
 
313
  }
314
 
315
  return $content;
@@ -409,7 +423,7 @@ class ES_Reports_Table extends ES_List_Table {
409
  }
410
 
411
  if ( ! empty( $where_query ) ) {
412
- $sql .= ' WHERE ' . $where_query;
413
  $add_where_clause = false;
414
  }
415
 
@@ -417,7 +431,7 @@ class ES_Reports_Table extends ES_List_Table {
417
  if ( ! $add_where_clause ) {
418
  $sql .= $wpdb->prepare( ' AND status = %s', $filter_reports_by_campaign_status );
419
  } else {
420
- $sql .= $wpdb->prepare( ' WHERE status = %s', $filter_reports_by_campaign_status );
421
  $add_where_clause = false;
422
  }
423
  }
@@ -451,9 +465,9 @@ class ES_Reports_Table extends ES_List_Table {
451
  $order_by_clause = " ORDER BY {$order_by} {$order}, {$default_order_by} DESC";
452
  }
453
 
454
- $sql .= $order_by_clause;
455
- $sql .= " LIMIT $per_page";
456
- $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
457
  $result = $wpbd->get_results( $sql, 'ARRAY_A' );
458
 
459
  } else {
@@ -551,7 +565,7 @@ class ES_Reports_Table extends ES_List_Table {
551
  <?php
552
  $allowedtags = ig_es_allowed_html_tags_in_esc();
553
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
554
- $statuses = array(
555
  'Sent' => __( 'Completed', 'email-subscribers' ),
556
  'In Queue' => __( 'In Queue', 'email-subscribers' ),
557
  'Sending' => __( 'Sending', 'email-subscribers' ),
20
  )
21
  );
22
 
 
23
  add_action( 'admin_footer', array( $this, 'display_preview_email' ), 10 );
24
  }
25
 
27
 
28
  $campaign_id = ig_es_get_request_data( 'campaign_id' );
29
  $campaign_type = '';
30
+ // Since, currently we are not passing campaign_id with broadcast $campaign_type will remain empty for broadcast
31
+ if ( ! empty( $campaign_id ) ) {
32
  $campaign_type = ES()->campaigns_db->get_campaign_type_by_id( $campaign_id );
33
  }
34
 
35
  $campaign_types = array( 'sequence', 'sequence_message' );
36
+ // Only if it is sequence then control will transfer to Sequence Reports class.
37
+ if ( ! empty( $campaign_type ) && in_array( $campaign_type, $campaign_types, true ) ) {
38
  if ( ES()->is_pro() ) {
39
  $reports = ES_Pro_Sequence_Reports::get_instance();
40
  $reports->es_sequence_reports_callback();
62
  /* translators: %s: Cron url */
63
  $content = '<a href="' . esc_url( $cron_url ) . '" class="px-3 py-2 ig-es-imp-button">' . esc_html__( 'Send Queued Emails Now', 'email-subscribers' ) . '</a>';
64
  } else {
65
+ $content = '<span class="ig-es-send-queue-emails px-3 button-disabled">' . esc_html__( 'Send Queued Emails Now', 'email-subscribers' ) . '</span>';
66
  $content .= '<br /><span class="es-helper pl-6">' . esc_html__( 'No emails found in queue', 'email-subscribers' ) . '</span>';
67
  }
68
  ?>
103
  }
104
  }
105
 
 
106
  }
107
 
108
  public function screen_option() {
116
 
117
  add_screen_option( $option, $args );
118
 
119
+ }
120
 
121
  /** Text displayed when no list data is available */
122
  public function no_items() {
126
  /**
127
  * Generates content for a single row of the table.
128
  * Overrides WP_List_Table class single_row function.
129
+ *
130
  * @since 4.7.8
131
  *
132
  * @param object|array $item The current item
140
  /**
141
  * Render a column when no column specific method exist.
142
  *
143
+ * @param array $item
144
  * @param string $column_name
145
  *
146
  * @return mixed
183
  $report_status = $item['status'];
184
  $status_html = '';
185
  if ( IG_ES_MAILING_QUEUE_STATUS_SENT === $report_status ) {
186
+ $status_html = sprintf(
187
+ '<svg class="flex-shrink-0 h-6 w-6 text-green-400" fill="currentColor" viewBox="0 0 20 20">
188
  <title>%s</title>
189
  <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
190
+ </svg>',
191
+ __( 'Sent', 'email-subscribers' )
192
+ );
193
  } else {
194
  if ( IG_ES_MAILING_QUEUE_STATUS_SENDING === $report_status ) {
195
+ $status_html = sprintf(
196
+ '<svg class="flex-shrink-0 h-6 w-6 text-yellow-400 inline" fill="currentColor" viewBox="0 0 20 20">
197
  <title>%s</title>
198
  <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-8.707l-3-3a1 1 0 00-1.414 1.414L10.586 9H7a1 1 0 100 2h3.586l-1.293 1.293a1 1 0 101.414 1.414l3-3a1 1 0 000-1.414z" clip-rule="evenodd"/>
199
+ </svg>',
200
+ __( 'Sending', 'email-subscribers' )
201
+ );
202
  } elseif ( IG_ES_MAILING_QUEUE_STATUS_PAUSED === $report_status ) {
203
+ $status_html = sprintf(
204
+ '<svg xmlns="http://www.w3.org/2000/svg" class="flex-shrink-0 h-6 w-6 inline text-gray-500" viewBox="0 0 20 20" fill="currentColor">
205
  <title>%s</title>
206
  <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
207
+ </svg>',
208
+ __( 'Paused', 'email-subscribers' )
209
+ );
210
  } elseif ( IG_ES_MAILING_QUEUE_STATUS_QUEUED === $report_status ) {
211
+ $status_html = sprintf(
212
+ '<svg class="flex-shrink-0 h-6 w-6 inline text-orange-400" fill="currentColor" viewBox="0 0 20 20">
213
  <title>%s</title>
214
  <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"/>
215
+ </svg>',
216
+ __( 'Scheduled', 'email-subscribers' )
217
+ );
218
  }
219
  $actions = array();
220
  if ( in_array( $report_status, array( IG_ES_MAILING_QUEUE_STATUS_QUEUED, IG_ES_MAILING_QUEUE_STATUS_SENDING ), true ) ) {
221
+ $actions['send_now'] = $this->prepare_send_now_url( $item );
222
  }
223
 
224
  $actions = apply_filters( 'ig_es_report_row_actions', $actions, $item );
275
  */
276
  public function get_columns() {
277
  $columns = array(
278
+ 'cb' => '<input type="checkbox" />',
279
+ 'subject' => __( 'Subject', 'email-subscribers' ),
280
+ 'type' => __( 'Type', 'email-subscribers' ),
281
+ 'status' => __( 'Status', 'email-subscribers' ),
282
+ 'start_at' => __( 'Start Date', 'email-subscribers' ),
283
+ 'finish_at' => __( 'End Date', 'email-subscribers' ),
284
+ 'count' => __( 'Total contacts', 'email-subscribers' ),
285
+ 'total_sent' => __( 'Total sent', 'email-subscribers' ),
286
  );
287
 
288
  return $columns;
315
  $content = '';
316
  if ( ! empty( $cron_url ) ) {
317
  /* translators: %s: Cron url */
318
+ $content = sprintf(
319
+ '<a href="%s" target="_blank">
320
  <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 inline text-yellow-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
321
  <title>%s</title>
322
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z" />
323
+ </svg></a>',
324
+ $cron_url,
325
+ __( 'Send now', 'email-subscribers' )
326
+ );
327
  }
328
 
329
  return $content;
423
  }
424
 
425
  if ( ! empty( $where_query ) ) {
426
+ $sql .= ' WHERE ' . $where_query;
427
  $add_where_clause = false;
428
  }
429
 
431
  if ( ! $add_where_clause ) {
432
  $sql .= $wpdb->prepare( ' AND status = %s', $filter_reports_by_campaign_status );
433
  } else {
434
+ $sql .= $wpdb->prepare( ' WHERE status = %s', $filter_reports_by_campaign_status );
435
  $add_where_clause = false;
436
  }
437
  }
465
  $order_by_clause = " ORDER BY {$order_by} {$order}, {$default_order_by} DESC";
466
  }
467
 
468
+ $sql .= $order_by_clause;
469
+ $sql .= " LIMIT $per_page";
470
+ $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
471
  $result = $wpbd->get_results( $sql, 'ARRAY_A' );
472
 
473
  } else {
565
  <?php
566
  $allowedtags = ig_es_allowed_html_tags_in_esc();
567
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
568
+ $statuses = array(
569
  'Sent' => __( 'Completed', 'email-subscribers' ),
570
  'In Queue' => __( 'In Queue', 'email-subscribers' ),
571
  'Sending' => __( 'Sending', 'email-subscribers' ),
lite/includes/classes/class-es-templates-table.php CHANGED
@@ -29,7 +29,7 @@ class ES_Templates_Table {
29
  }
30
  $values = get_post_custom( $post->ID );
31
 
32
- $selected = isset( $values['es_template_type'] ) ? esc_attr( $values['es_template_type'][0] ) : '';
33
 
34
  $template_type = ES_Common::get_campaign_types( array( 'sequence' ) );
35
  ?>
@@ -102,7 +102,7 @@ class ES_Templates_Table {
102
  if ( ! empty( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'update-post_' . $post_id ) ) {
103
 
104
  $es_template_type = ig_es_get_data( $_POST, 'es_template_type', '', true );
105
-
106
  if ( ! empty( $es_template_type ) ) {
107
  update_post_meta( $post_id, 'es_template_type', $es_template_type );
108
  }
@@ -194,7 +194,7 @@ class ES_Templates_Table {
194
  $es_template_body = str_replace( '{{EMAIL}}', $useremail, $es_template_body );
195
  $es_template_body = str_replace( '{{FIRSTNAME}}', $first_name, $es_template_body );
196
  $es_template_body = str_replace( '{{LASTNAME}}', $last_name, $es_template_body );
197
- $allowedtags = ig_es_allowed_html_tags_in_esc();
198
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
199
 
200
  if ( has_post_thumbnail( $template_id ) ) {
@@ -247,7 +247,7 @@ class ES_Templates_Table {
247
  <div class="es-clear-preview"></div>
248
  </div>
249
  </div>';
250
- echo wp_kses( apply_filters( 'the_content', $html ), $allowedtags);
251
  } else {
252
  echo esc_html__( 'Please publish it or save it as a draft.', 'email-subscribers' );
253
  }
@@ -278,7 +278,7 @@ class ES_Templates_Table {
278
  switch ( $column ) {
279
  case 'es_template_type':
280
  $type = get_post_meta( $post->ID, 'es_template_type', true );
281
- $type = sanitize_text_field(strtolower( $type ));
282
  $type = ( 'newsletter' === $type ) ? __( 'Broadcast', 'email-subscribers' ) : $type;
283
  $type = ucwords( str_replace( '_', ' ', $type ) );
284
  echo esc_html( $type );
29
  }
30
  $values = get_post_custom( $post->ID );
31
 
32
+ $selected = isset( $values['es_template_type'] ) ? esc_attr( $values['es_template_type'][0] ) : '';
33
 
34
  $template_type = ES_Common::get_campaign_types( array( 'sequence' ) );
35
  ?>
102
  if ( ! empty( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'update-post_' . $post_id ) ) {
103
 
104
  $es_template_type = ig_es_get_data( $_POST, 'es_template_type', '', true );
105
+
106
  if ( ! empty( $es_template_type ) ) {
107
  update_post_meta( $post_id, 'es_template_type', $es_template_type );
108
  }
194
  $es_template_body = str_replace( '{{EMAIL}}', $useremail, $es_template_body );
195
  $es_template_body = str_replace( '{{FIRSTNAME}}', $first_name, $es_template_body );
196
  $es_template_body = str_replace( '{{LASTNAME}}', $last_name, $es_template_body );
197
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
198
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
199
 
200
  if ( has_post_thumbnail( $template_id ) ) {
247
  <div class="es-clear-preview"></div>
248
  </div>
249
  </div>';
250
+ echo wp_kses( apply_filters( 'the_content', $html ), $allowedtags );
251
  } else {
252
  echo esc_html__( 'Please publish it or save it as a draft.', 'email-subscribers' );
253
  }
278
  switch ( $column ) {
279
  case 'es_template_type':
280
  $type = get_post_meta( $post->ID, 'es_template_type', true );
281
+ $type = sanitize_text_field( strtolower( $type ) );
282
  $type = ( 'newsletter' === $type ) ? __( 'Broadcast', 'email-subscribers' ) : $type;
283
  $type = ucwords( str_replace( '_', ' ', $type ) );
284
  echo esc_html( $type );
lite/includes/classes/class-es-tools.php CHANGED
@@ -47,13 +47,13 @@ class ES_Tools {
47
  if ( ! empty( $email ) ) {
48
 
49
  $merge_tags = array( 'attachments' => $attachments );
50
-
51
  if ( ! empty( $campaign_id ) ) {
52
  $merge_tags['campaign_id'] = $campaign_id;
53
  }
54
-
55
  $content = ES_Common::es_process_template_body( $content, $template_id, $campaign_id );
56
-
57
  $response = ES()->mailer->send_test_email( $email, $subject, $content, $merge_tags );
58
 
59
  if ( $response && 'SUCCESS' === $response['status'] ) {
47
  if ( ! empty( $email ) ) {
48
 
49
  $merge_tags = array( 'attachments' => $attachments );
50
+
51
  if ( ! empty( $campaign_id ) ) {
52
  $merge_tags['campaign_id'] = $campaign_id;
53
  }
54
+
55
  $content = ES_Common::es_process_template_body( $content, $template_id, $campaign_id );
56
+
57
  $response = ES()->mailer->send_test_email( $email, $subject, $content, $merge_tags );
58
 
59
  if ( $response && 'SUCCESS' === $response['status'] ) {
lite/includes/classes/class-es-widget.php CHANGED
@@ -72,10 +72,10 @@ class ES_Widget extends WP_Widget {
72
  <p>
73
  <label for="widget-email-subscribers-2-es_group"><?php esc_html_e( 'Subscriber List' ); ?></label>
74
  <select id="<?php echo esc_attr( $this->get_field_id( 'subscribers_group' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'subscribers_group' ) ); ?>" class="widefat" style="width:100%;">
75
- <?php
76
  $lists_dropdown = ES_Common::prepare_list_dropdown_options( $subscribers_group );
77
- $allowedtags = ig_es_allowed_html_tags_in_esc();
78
- echo wp_kses( $lists_dropdown , $allowedtags );
79
  ?>
80
  </select>
81
  </p>
72
  <p>
73
  <label for="widget-email-subscribers-2-es_group"><?php esc_html_e( 'Subscriber List' ); ?></label>
74
  <select id="<?php echo esc_attr( $this->get_field_id( 'subscribers_group' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'subscribers_group' ) ); ?>" class="widefat" style="width:100%;">
75
+ <?php
76
  $lists_dropdown = ES_Common::prepare_list_dropdown_options( $subscribers_group );
77
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
78
+ echo wp_kses( $lists_dropdown, $allowedtags );
79
  ?>
80
  </select>
81
  </p>
lite/includes/classes/class-ig-es-background-process-helper.php CHANGED
@@ -35,7 +35,7 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
35
 
36
  /**
37
  * Contructor
38
- *
39
  * @since 4.6.3
40
  */
41
  private function __construct() {
@@ -47,7 +47,7 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
47
  * Get single instance of IG_ES_Background_Process_Helper
48
  *
49
  * @return IG_ES_Background_Process_Helper Singleton object of IG_ES_Background_Process_Helper
50
- *
51
  * @since 4.6.3
52
  */
53
  public static function get_instance() {
@@ -66,7 +66,7 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
66
  * of the maximum WordPress memory.
67
  *
68
  * @return bool
69
- *
70
  * @since 4.6.3
71
  */
72
  public static function memory_exceeded() {
@@ -84,7 +84,7 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
84
  * Get memory limit.
85
  *
86
  * @return int
87
- *
88
  * @since 4.6.3
89
  */
90
  public static function get_memory_limit() {
@@ -110,12 +110,12 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
110
  * A timeout limit of 30s is common on shared hosting.
111
  *
112
  * @param string $start_time start timestamp.
113
- * @param float $fraction Time fraction.
114
- *
115
  * @return bool
116
- *
117
  * @since 4.6.3
118
- *
119
  * @since Added $fraction parameter
120
  */
121
  public static function time_exceeded( $start_time = 0, $fraction = 0.6 ) {
@@ -131,10 +131,10 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
131
  }
132
 
133
  /**
134
- * Method to get Server time limit
135
- *
136
  * @return int $time_limit Server time limit.
137
- *
138
  * @since 4.6.3
139
  */
140
  public static function get_time_limit() {
@@ -151,14 +151,14 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
151
 
152
  /**
153
  * Method to add new action scheduler task. Task added by this function are called by Action Scheduler library when execution time comes.
154
- *
155
  * @param string $action Action name.
156
- * @param array $action_args Action arguements.
157
- * @param bool $process_asynchronously Should process action asynchronously.
158
- * @param bool $should_wait Should wait before making asynchronous request to process the action.
159
- *
160
  * @return int|bool $action_id Action ID on success or false on failure.
161
- *
162
  * @since 4.6.3
163
  */
164
  public static function add_action_scheduler_task( $action = '', $action_args = array(), $process_asynchronously = true, $should_wait = false, $time = 0 ) {
@@ -168,7 +168,7 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
168
  }
169
 
170
  if ( function_exists( 'as_schedule_single_action' ) ) {
171
- $time = ! empty( $time ) ? $time : time();
172
  $action_id = as_schedule_single_action( $time, $action, array( $action_args ), 'email-subscribers' );
173
 
174
  if ( ! empty( $action_id ) ) {
@@ -206,9 +206,9 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
206
  /**
207
  * Method to get required waiting time in seconds before making async request.
208
  * Chaining async requests can crash MySQL. A brief waiting period in PHP helps in preventing that.
209
- *
210
  * @return int Waiting time in seconds.
211
- *
212
  * @since 4.6.3
213
  */
214
  public static function get_wait_seconds() {
@@ -219,10 +219,10 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
219
  * Method to send asynchronous background request to admin-ajax.
220
  *
221
  * @param array $request_args Async request's arguments.
222
- * @param bool $should_wait Should wait before making this async request.
223
- *
224
  * @return array $response Async request's response.
225
- *
226
  * @since 4.6.3
227
  */
228
  public static function send_async_ajax_request( $request_args = array(), $should_wait = false ) {
@@ -236,7 +236,7 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
236
  // Should wait before making async request.
237
  if ( $should_wait ) {
238
  $wait_seconds = self::get_wait_seconds();
239
-
240
  if ( $wait_seconds ) {
241
 
242
  // Sleep to prevent crashing of MYSQL due to chaining of async request.
@@ -252,9 +252,9 @@ if ( ! class_exists( 'IG_ES_Background_Process_Helper' ) ) {
252
  'cookies' => $_COOKIE,
253
  'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
254
  );
255
-
256
  $args = apply_filters( 'ig_es_async_request_args', $args );
257
-
258
  // Make a asynchronous request.
259
  $response = wp_remote_get( esc_url_raw( $admin_ajax_url ), $args );
260
 
35
 
36
  /**
37
  * Contructor
38
+ *
39
  * @since 4.6.3
40
  */
41
  private function __construct() {
47
  * Get single instance of IG_ES_Background_Process_Helper
48
  *
49
  * @return IG_ES_Background_Process_Helper Singleton object of IG_ES_Background_Process_Helper
50
+ *
51
  * @since 4.6.3
52
  */
53
  public static function get_instance() {
66
  * of the maximum WordPress memory.
67
  *
68
  * @return bool
69
+ *
70
  * @since 4.6.3
71
  */
72
  public static function memory_exceeded() {
84
  * Get memory limit.
85
  *
86
  * @return int
87
+ *
88
  * @since 4.6.3
89
  */
90
  public static function get_memory_limit() {
110
  * A timeout limit of 30s is common on shared hosting.
111
  *
112
  * @param string $start_time start timestamp.
113
+ * @param float $fraction Time fraction.
114
+ *
115
  * @return bool
116
+ *
117
  * @since 4.6.3
118
+ *
119
  * @since Added $fraction parameter
120
  */
121
  public static function time_exceeded( $start_time = 0, $fraction = 0.6 ) {
131
  }
132
 
133
  /**
134
+ * Method to get Server time limit
135
+ *
136
  * @return int $time_limit Server time limit.
137
+ *
138
  * @since 4.6.3
139
  */
140
  public static function get_time_limit() {
151
 
152
  /**
153
  * Method to add new action scheduler task. Task added by this function are called by Action Scheduler library when execution time comes.
154
+ *
155
  * @param string $action Action name.
156
+ * @param array $action_args Action arguements.
157
+ * @param bool $process_asynchronously Should process action asynchronously.
158
+ * @param bool $should_wait Should wait before making asynchronous request to process the action.
159
+ *
160
  * @return int|bool $action_id Action ID on success or false on failure.
161
+ *
162
  * @since 4.6.3
163
  */
164
  public static function add_action_scheduler_task( $action = '', $action_args = array(), $process_asynchronously = true, $should_wait = false, $time = 0 ) {
168
  }
169
 
170
  if ( function_exists( 'as_schedule_single_action' ) ) {
171
+ $time = ! empty( $time ) ? $time : time();
172
  $action_id = as_schedule_single_action( $time, $action, array( $action_args ), 'email-subscribers' );
173
 
174
  if ( ! empty( $action_id ) ) {
206
  /**
207
  * Method to get required waiting time in seconds before making async request.
208
  * Chaining async requests can crash MySQL. A brief waiting period in PHP helps in preventing that.
209
+ *
210
  * @return int Waiting time in seconds.
211
+ *
212
  * @since 4.6.3
213
  */
214
  public static function get_wait_seconds() {
219
  * Method to send asynchronous background request to admin-ajax.
220
  *
221
  * @param array $request_args Async request's arguments.
222
+ * @param bool $should_wait Should wait before making this async request.
223
+ *
224
  * @return array $response Async request's response.
225
+ *
226
  * @since 4.6.3
227
  */
228
  public static function send_async_ajax_request( $request_args = array(), $should_wait = false ) {
236
  // Should wait before making async request.
237
  if ( $should_wait ) {
238
  $wait_seconds = self::get_wait_seconds();
239
+
240
  if ( $wait_seconds ) {
241
 
242
  // Sleep to prevent crashing of MYSQL due to chaining of async request.
252
  'cookies' => $_COOKIE,
253
  'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
254
  );
255
+
256
  $args = apply_filters( 'ig_es_async_request_args', $args );
257
+
258
  // Make a asynchronous request.
259
  $response = wp_remote_get( esc_url_raw( $admin_ajax_url ), $args );
260
 
lite/includes/classes/class-ig-es-subscriber-query.php CHANGED
@@ -14,17 +14,17 @@ class IG_ES_Subscribers_Query {
14
  private $args = array();
15
 
16
  private $defaults = array(
17
- 'select' => null,
18
- 'join' => null,
19
- 'status' => null,
20
- 'status__not_in' => null,
21
- 'where' => null,
22
- 'having' => null,
23
- 'orderby' => null,
24
- 'order' => null,
25
- 'groupby' => null,
26
- 'limit' => null,
27
- 'offset' => null,
28
 
29
  'return_ids' => false,
30
  'return_count' => false,
@@ -86,7 +86,7 @@ class IG_ES_Subscribers_Query {
86
  'id',
87
  'email',
88
  'wp_user_id',
89
- 'country_code'
90
  );
91
 
92
  private $action_fields = array(
@@ -106,14 +106,13 @@ class IG_ES_Subscribers_Query {
106
  '_click_link__not_in',
107
  '_lists__in',
108
  '_lists__not_in',
109
- '_subscribed_before'
110
  );
111
 
112
  private static $_instance = null;
113
 
114
  public function __construct( $args = null, $campaign_id = null ) {
115
 
116
-
117
  if ( ! is_null( $args ) ) {
118
  return $this->run( $args, $campaign_id );
119
  }
@@ -169,7 +168,7 @@ class IG_ES_Subscribers_Query {
169
  }
170
 
171
  $this->args = apply_filters( 'ig_es_subscriber_query_args', $this->args );
172
-
173
  if ( ! empty( $this->args['queue__not_in'] ) ) {
174
  $join = "LEFT JOIN {$wpbd->prefix}ig_queue AS queue ON subscribers.id = queue.contact_id";
175
  if ( ! empty( $this->args['queue__not_in'] ) ) {
@@ -185,7 +184,7 @@ class IG_ES_Subscribers_Query {
185
 
186
  if ( ! empty( $and_conditions ) ) {
187
  foreach ( $and_conditions as $j => $condition ) {
188
-
189
  $field = isset( $condition['field'] ) ? $condition['field'] : ( isset( $condition[0] ) ? $condition[0] : null );
190
  $operator = isset( $condition['operator'] ) ? $condition['operator'] : ( isset( $condition[1] ) ? $condition[1] : null );
191
  $value = isset( $condition['value'] ) ? $condition['value'] : ( isset( $condition[2] ) ? $condition[2] : null );
@@ -205,26 +204,26 @@ class IG_ES_Subscribers_Query {
205
 
206
  if ( ! empty( $this->args['conditions'] ) ) {
207
  foreach ( $this->args['conditions'] as $i => $and_conditions ) {
208
-
209
  $sub_cond = array();
210
-
211
  if ( ! empty( $and_conditions ) ) {
212
  foreach ( $and_conditions as $j => $condition ) {
213
-
214
  $field = isset( $condition['field'] ) ? $condition['field'] : ( isset( $condition[0] ) ? $condition[0] : null );
215
  $operator = isset( $condition['operator'] ) ? $condition['operator'] : ( isset( $condition[1] ) ? $condition[1] : null );
216
  $value = isset( $condition['value'] ) ? $condition['value'] : ( isset( $condition[2] ) ? $condition[2] : null );
217
-
218
  if ( ! in_array( $field, $this->action_fields, true ) ) {
219
  $sub_cond[] = $this->get_condition( $field, $operator, $value );
220
  } else {
221
-
222
  $value = $this->remove_empty_values( $value );
223
-
224
  $alias = 'actions' . $field . '_' . $i . '_' . $j;
225
-
226
  if ( '_lists__in' === $field ) {
227
-
228
  if ( $value ) {
229
  $sub_cond[] = "lists_subscribers.contact_id IN ( SELECT contact_id FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id IN (" . implode( ',', array_filter( $value, 'is_numeric' ) ) . ') )';
230
  }
@@ -236,7 +235,7 @@ class IG_ES_Subscribers_Query {
236
  $sub_cond[] = "lists_subscribers.contact_id NOT IN ( SELECT contact_id FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id <> 0 )";
237
  }
238
  } elseif ( 0 === strpos( $field, '_sent' ) ) {
239
-
240
  $join = "LEFT JOIN {$wpbd->prefix}ig_actions AS $alias ON $alias.type = " . IG_MESSAGE_SENT . " AND subscribers.id = $alias.contact_id";
241
  if ( ( '_sent' === $field || '_sent__not_in' === $field ) ) {
242
  if ( $value ) {
@@ -245,7 +244,7 @@ class IG_ES_Subscribers_Query {
245
  $join .= " AND $alias.campaign_id IS NOT NULL AND $alias.campaign_id <> 0";
246
  }
247
  }
248
-
249
  if ( '_sent' === $field ) {
250
  $sub_cond[] = "$alias.contact_id IS NOT NULL";
251
  } elseif ( '_sent__not_in' === $field ) {
@@ -255,11 +254,11 @@ class IG_ES_Subscribers_Query {
255
  } elseif ( '_sent_after' === $field ) {
256
  $sub_cond[] = "$alias.timestamp >= " . $this->get_timestamp( $value );
257
  }
258
-
259
  $joins[] = $join;
260
-
261
  } elseif ( 0 === strpos( $field, '_open' ) ) {
262
-
263
  $join = "LEFT JOIN {$wpbd->prefix}ig_actions AS $alias ON $alias.type = " . IG_MESSAGE_OPEN . " AND subscribers.id = $alias.contact_id";
264
  if ( ( '_open' === $field || '_open__not_in' === $field ) ) {
265
  if ( $value ) {
@@ -268,7 +267,7 @@ class IG_ES_Subscribers_Query {
268
  $join .= " AND $alias.campaign_id IS NOT NULL AND $alias.campaign_id <> 0";
269
  }
270
  }
271
-
272
  if ( '_open' === $field ) {
273
  $sub_cond[] = "$alias.contact_id IS NOT NULL";
274
  } elseif ( '_open__not_in' === $field ) {
@@ -278,13 +277,13 @@ class IG_ES_Subscribers_Query {
278
  } elseif ( '_open_after' === $field ) {
279
  $sub_cond[] = "$alias.timestamp >= " . $this->get_timestamp( $value );
280
  }
281
-
282
  $joins[] = $join;
283
-
284
  } elseif ( 0 === strpos( $field, '_click' ) ) {
285
-
286
  $join = "LEFT JOIN {$wpbd->prefix}ig_actions AS $alias ON $alias.type = " . IG_LINK_CLICK . " AND subscribers.id = $alias.contact_id";
287
-
288
  if ( ( '_click' === $field || '_click__not_in' === $field ) ) {
289
  if ( $value ) {
290
  $join .= " AND $alias.campaign_id IN (" . implode( ',', array_filter( $value, 'is_numeric' ) ) . ')';
@@ -306,7 +305,7 @@ class IG_ES_Subscribers_Query {
306
  }
307
  $joins[] = "LEFT JOIN {$wpbd->prefix}ig_links AS {$alias}{$field} ON {$alias}{$field}.link IN ('" . implode( "','", $value ) . "')";
308
  }
309
-
310
  if ( '_click' === $field ) {
311
  $sub_cond[] = "$alias.contact_id IS NOT NULL";
312
  } elseif ( '_click__not_in' === $field ) {
@@ -320,10 +319,9 @@ class IG_ES_Subscribers_Query {
320
  } elseif ( '_click_link__not_in' === $field ) {
321
  $sub_cond[] = "$alias.contact_id IS NULL";
322
  }
323
-
324
  $joins[] = $join;
325
  }
326
-
327
  }
328
  }
329
  }
@@ -333,14 +331,13 @@ class IG_ES_Subscribers_Query {
333
  }
334
  }
335
  }
336
-
337
  if ( ! empty( $cond ) ) {
338
  $wheres[] = 'AND ( ' . implode( ' AND ', $cond ) . ' )';
339
  }
340
 
341
- $joins[] = "LEFT JOIN {$wpbd->prefix}ig_lists_contacts AS lists_subscribers ON subscribers.id = lists_subscribers.contact_id";
342
  $wheres[] = "AND lists_subscribers.status IN( 'subscribed', 'confirmed' )";
343
-
344
 
345
  if ( ! is_bool( $this->args['lists'] ) ) {
346
  // unassigned members if NULL
@@ -371,7 +368,7 @@ class IG_ES_Subscribers_Query {
371
 
372
  $ordering = isset( $this->args['order'][0] ) ? strtoupper( $this->args['order'][0] ) : 'ASC';
373
  $orders = array();
374
-
375
  foreach ( $this->args['orderby'] as $i => $orderby ) {
376
  $ordering = isset( $this->args['order'][ $i ] ) ? strtoupper( $this->args['order'][ $i ] ) : $ordering;
377
  if ( in_array( $orderby, $this->fields ) ) {
@@ -381,10 +378,9 @@ class IG_ES_Subscribers_Query {
381
  $orders[] = "$orderby $ordering";
382
  }
383
  }
384
-
385
  }
386
 
387
- $select = 'SELECT';
388
  $select .= ' ' . implode( ', ', $this->args['select'] );
389
 
390
  $from = "FROM {$wpbd->prefix}ig_contacts AS subscribers";
@@ -426,8 +422,8 @@ class IG_ES_Subscribers_Query {
426
  $sql = apply_filters( 'ig_es_subscriber_query_sql', $sql, $this->args, $campaign_id );
427
 
428
  if ( $this->args['return_sql'] ) {
429
- $result = $sql;
430
- $this->last_query = $sql;
431
  $this->last_error = null;
432
  $this->last_result = null;
433
  } else {
@@ -519,7 +515,7 @@ class IG_ES_Subscribers_Query {
519
  case 'contains_not':
520
  $value = addcslashes( $value, '_%\\' );
521
  $value = "'%$value%'";
522
-
523
  $f = "subscribers.$field";
524
  $c = $f . ' ' . ( $positive ? 'LIKE' : 'NOT LIKE' ) . " $value";
525
  if ( $is_empty && $positive || ! $positive ) {
@@ -533,7 +529,7 @@ class IG_ES_Subscribers_Query {
533
  case 'begin_with':
534
  $value = addcslashes( $value, '_%\\' );
535
  $value = "'$value%'";
536
-
537
  $f = "subscribers.$field";
538
  $c = $f . " LIKE $value";
539
 
14
  private $args = array();
15
 
16
  private $defaults = array(
17
+ 'select' => null,
18
+ 'join' => null,
19
+ 'status' => null,
20
+ 'status__not_in' => null,
21
+ 'where' => null,
22
+ 'having' => null,
23
+ 'orderby' => null,
24
+ 'order' => null,
25
+ 'groupby' => null,
26
+ 'limit' => null,
27
+ 'offset' => null,
28
 
29
  'return_ids' => false,
30
  'return_count' => false,
86
  'id',
87
  'email',
88
  'wp_user_id',
89
+ 'country_code',
90
  );
91
 
92
  private $action_fields = array(
106
  '_click_link__not_in',
107
  '_lists__in',
108
  '_lists__not_in',
109
+ '_subscribed_before',
110
  );
111
 
112
  private static $_instance = null;
113
 
114
  public function __construct( $args = null, $campaign_id = null ) {
115
 
 
116
  if ( ! is_null( $args ) ) {
117
  return $this->run( $args, $campaign_id );
118
  }
168
  }
169
 
170
  $this->args = apply_filters( 'ig_es_subscriber_query_args', $this->args );
171
+
172
  if ( ! empty( $this->args['queue__not_in'] ) ) {
173
  $join = "LEFT JOIN {$wpbd->prefix}ig_queue AS queue ON subscribers.id = queue.contact_id";
174
  if ( ! empty( $this->args['queue__not_in'] ) ) {
184
 
185
  if ( ! empty( $and_conditions ) ) {
186
  foreach ( $and_conditions as $j => $condition ) {
187
+
188
  $field = isset( $condition['field'] ) ? $condition['field'] : ( isset( $condition[0] ) ? $condition[0] : null );
189
  $operator = isset( $condition['operator'] ) ? $condition['operator'] : ( isset( $condition[1] ) ? $condition[1] : null );
190
  $value = isset( $condition['value'] ) ? $condition['value'] : ( isset( $condition[2] ) ? $condition[2] : null );
204
 
205
  if ( ! empty( $this->args['conditions'] ) ) {
206
  foreach ( $this->args['conditions'] as $i => $and_conditions ) {
207
+
208
  $sub_cond = array();
209
+
210
  if ( ! empty( $and_conditions ) ) {
211
  foreach ( $and_conditions as $j => $condition ) {
212
+
213
  $field = isset( $condition['field'] ) ? $condition['field'] : ( isset( $condition[0] ) ? $condition[0] : null );
214
  $operator = isset( $condition['operator'] ) ? $condition['operator'] : ( isset( $condition[1] ) ? $condition[1] : null );
215
  $value = isset( $condition['value'] ) ? $condition['value'] : ( isset( $condition[2] ) ? $condition[2] : null );
216
+
217
  if ( ! in_array( $field, $this->action_fields, true ) ) {
218
  $sub_cond[] = $this->get_condition( $field, $operator, $value );
219
  } else {
220
+
221
  $value = $this->remove_empty_values( $value );
222
+
223
  $alias = 'actions' . $field . '_' . $i . '_' . $j;
224
+
225
  if ( '_lists__in' === $field ) {
226
+
227
  if ( $value ) {
228
  $sub_cond[] = "lists_subscribers.contact_id IN ( SELECT contact_id FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id IN (" . implode( ',', array_filter( $value, 'is_numeric' ) ) . ') )';
229
  }
235
  $sub_cond[] = "lists_subscribers.contact_id NOT IN ( SELECT contact_id FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id <> 0 )";
236
  }
237
  } elseif ( 0 === strpos( $field, '_sent' ) ) {
238
+
239
  $join = "LEFT JOIN {$wpbd->prefix}ig_actions AS $alias ON $alias.type = " . IG_MESSAGE_SENT . " AND subscribers.id = $alias.contact_id";
240
  if ( ( '_sent' === $field || '_sent__not_in' === $field ) ) {
241
  if ( $value ) {
244
  $join .= " AND $alias.campaign_id IS NOT NULL AND $alias.campaign_id <> 0";
245
  }
246
  }
247
+
248
  if ( '_sent' === $field ) {
249
  $sub_cond[] = "$alias.contact_id IS NOT NULL";
250
  } elseif ( '_sent__not_in' === $field ) {
254
  } elseif ( '_sent_after' === $field ) {
255
  $sub_cond[] = "$alias.timestamp >= " . $this->get_timestamp( $value );
256
  }
257
+
258
  $joins[] = $join;
259
+
260
  } elseif ( 0 === strpos( $field, '_open' ) ) {
261
+
262
  $join = "LEFT JOIN {$wpbd->prefix}ig_actions AS $alias ON $alias.type = " . IG_MESSAGE_OPEN . " AND subscribers.id = $alias.contact_id";
263
  if ( ( '_open' === $field || '_open__not_in' === $field ) ) {
264
  if ( $value ) {
267
  $join .= " AND $alias.campaign_id IS NOT NULL AND $alias.campaign_id <> 0";
268
  }
269
  }
270
+
271
  if ( '_open' === $field ) {
272
  $sub_cond[] = "$alias.contact_id IS NOT NULL";
273
  } elseif ( '_open__not_in' === $field ) {
277
  } elseif ( '_open_after' === $field ) {
278
  $sub_cond[] = "$alias.timestamp >= " . $this->get_timestamp( $value );
279
  }
280
+
281
  $joins[] = $join;
282
+
283
  } elseif ( 0 === strpos( $field, '_click' ) ) {
284
+
285
  $join = "LEFT JOIN {$wpbd->prefix}ig_actions AS $alias ON $alias.type = " . IG_LINK_CLICK . " AND subscribers.id = $alias.contact_id";
286
+
287
  if ( ( '_click' === $field || '_click__not_in' === $field ) ) {
288
  if ( $value ) {
289
  $join .= " AND $alias.campaign_id IN (" . implode( ',', array_filter( $value, 'is_numeric' ) ) . ')';
305
  }
306
  $joins[] = "LEFT JOIN {$wpbd->prefix}ig_links AS {$alias}{$field} ON {$alias}{$field}.link IN ('" . implode( "','", $value ) . "')";
307
  }
308
+
309
  if ( '_click' === $field ) {
310
  $sub_cond[] = "$alias.contact_id IS NOT NULL";
311
  } elseif ( '_click__not_in' === $field ) {
319
  } elseif ( '_click_link__not_in' === $field ) {
320
  $sub_cond[] = "$alias.contact_id IS NULL";
321
  }
322
+
323
  $joins[] = $join;
324
  }
 
325
  }
326
  }
327
  }
331
  }
332
  }
333
  }
334
+
335
  if ( ! empty( $cond ) ) {
336
  $wheres[] = 'AND ( ' . implode( ' AND ', $cond ) . ' )';
337
  }
338
 
339
+ $joins[] = "LEFT JOIN {$wpbd->prefix}ig_lists_contacts AS lists_subscribers ON subscribers.id = lists_subscribers.contact_id";
340
  $wheres[] = "AND lists_subscribers.status IN( 'subscribed', 'confirmed' )";
 
341
 
342
  if ( ! is_bool( $this->args['lists'] ) ) {
343
  // unassigned members if NULL
368
 
369
  $ordering = isset( $this->args['order'][0] ) ? strtoupper( $this->args['order'][0] ) : 'ASC';
370
  $orders = array();
371
+
372
  foreach ( $this->args['orderby'] as $i => $orderby ) {
373
  $ordering = isset( $this->args['order'][ $i ] ) ? strtoupper( $this->args['order'][ $i ] ) : $ordering;
374
  if ( in_array( $orderby, $this->fields ) ) {
378
  $orders[] = "$orderby $ordering";
379
  }
380
  }
 
381
  }
382
 
383
+ $select = 'SELECT';
384
  $select .= ' ' . implode( ', ', $this->args['select'] );
385
 
386
  $from = "FROM {$wpbd->prefix}ig_contacts AS subscribers";
422
  $sql = apply_filters( 'ig_es_subscriber_query_sql', $sql, $this->args, $campaign_id );
423
 
424
  if ( $this->args['return_sql'] ) {
425
+ $result = $sql;
426
+ $this->last_query = $sql;
427
  $this->last_error = null;
428
  $this->last_result = null;
429
  } else {
515
  case 'contains_not':
516
  $value = addcslashes( $value, '_%\\' );
517
  $value = "'%$value%'";
518
+
519
  $f = "subscribers.$field";
520
  $c = $f . ' ' . ( $positive ? 'LIKE' : 'NOT LIKE' ) . " $value";
521
  if ( $is_empty && $positive || ! $positive ) {
529
  case 'begin_with':
530
  $value = addcslashes( $value, '_%\\' );
531
  $value = "'$value%'";
532
+
533
  $f = "subscribers.$field";
534
  $c = $f . " LIKE $value";
535
 
lite/includes/classes/class-ig-es-trial.php CHANGED
@@ -7,7 +7,6 @@ if ( ! defined( 'ABSPATH' ) ) {
7
 
8
  /**
9
  * The trial-specific functionality of the plugin.
10
- *
11
  */
12
  class IG_ES_Trial {
13
 
@@ -29,7 +28,7 @@ class IG_ES_Trial {
29
 
30
  /**
31
  * Get class instance.
32
- *
33
  * @since 4.6.2
34
  */
35
  public static function get_instance() {
@@ -43,17 +42,17 @@ class IG_ES_Trial {
43
 
44
  /**
45
  * Method to get trial period
46
- *
47
  * @param string $period_in Period unit.
48
- *
49
  * @return int Trial period in second.
50
- *
51
  * @since 4.6.2
52
  */
53
  public function get_trial_period( $period_in = 'in_seconds' ) {
54
-
55
  $trial_period = 0;
56
-
57
  switch ( $period_in ) {
58
  case 'in_days':
59
  $trial_period = IG_ES_TRIAL_PERIOD_IN_DAYS;
@@ -65,16 +64,16 @@ class IG_ES_Trial {
65
 
66
  return $trial_period;
67
  }
68
-
69
  /**
70
  * Method to get total days since trial start date/time
71
- *
72
  * @return int $trial_time_in_days Trial period passed in days.
73
- *
74
  * @since 4.6.2
75
  */
76
  public function get_days_since_trial_started() {
77
-
78
  $current_time = time();
79
  $trial_time_in_days = 0;
80
  $trial_started_at = get_option( 'ig_es_trial_started_at' );
@@ -89,34 +88,34 @@ class IG_ES_Trial {
89
 
90
  /**
91
  * Method to get total remaining days in trial expiration.
92
- *
93
  * @return int $remaining_trial_days Remaining trial days.
94
- *
95
  * @since 4.6.2
96
  */
97
  public function get_remaining_trial_days() {
98
-
99
  $total_days_since_trial = $this->get_days_since_trial_started();
100
- $trial_period_in_days = $this->get_trial_period( 'in_days' );
101
- $remaining_trial_days = $trial_period_in_days - $total_days_since_trial;
102
 
103
  return $remaining_trial_days;
104
  }
105
-
106
  /**
107
  * Method to get trial expiry date
108
- *
109
  * @param string $date_format Date formate
110
- *
111
  * @return string $trial_expriy_date Trial expiry date.
112
- *
113
  * @since 4.6.2
114
  */
115
  public function get_trial_expiry_date( $date_format = 'Y-m-d H:i:s' ) {
116
-
117
  $trial_expriy_date = '';
118
- $trial_started_at = $this->get_trial_started_at();
119
-
120
  if ( ! empty( $trial_started_at ) ) {
121
  $trial_expires_at = $trial_started_at + $this->get_trial_period();
122
  $trial_expriy_date = gmdate( $date_format, $trial_expires_at );
@@ -124,12 +123,12 @@ class IG_ES_Trial {
124
 
125
  return $trial_expriy_date;
126
  }
127
-
128
  /**
129
  * Method to get trial started at timestamp.
130
- *
131
  * @return int $trial_started_at Trial started at timestamp.
132
- *
133
  * @since 4.6.2
134
  */
135
  public function get_trial_started_at() {
@@ -139,16 +138,16 @@ class IG_ES_Trial {
139
 
140
  /**
141
  * Method to show trial related notices to user.
142
- *
143
  * @since 4.6.2
144
  */
145
  public function show_trial_notices() {
146
-
147
  // Don't show trial notices untill onboarding is completed.
148
  if ( ! IG_ES_Onboarding::is_onboarding_completed() ) {
149
  return;
150
  }
151
-
152
  $is_trial = ES()->is_trial();
153
  $is_premium = ES()->is_premium();
154
  $is_premium_installed = ES()->is_premium_installed();
@@ -160,7 +159,7 @@ class IG_ES_Trial {
160
  if ( ! $is_trial && ! $is_premium && 'es_dashboard' !== $current_page ) {
161
  // Check whether user has performed any action(accept/reject) on consent notice for trial. 'yes' if performed.
162
  $trial_consent_given = get_option( 'ig_es_trial_consent', 'no' );
163
- if ( 'yes' !== $trial_consent_given ) {
164
  $show_trial_consent_notice = true;
165
  }
166
  }
@@ -170,7 +169,7 @@ class IG_ES_Trial {
170
  } else {
171
  ES_Admin_Notices::remove_notice( 'trial_consent' );
172
  }
173
-
174
  $show_offer_notice = false;
175
 
176
  // Add upgrade to premium nudging notice if user has opted for trial and is not a premium user and premium plugin is not installed on site and is not dashboard page.
@@ -182,15 +181,15 @@ class IG_ES_Trial {
182
  $max_nudging_day = max( $nudging_days );
183
 
184
  // Current day's number from start of trial.
185
- $remaining_trial_days = ES()->trial->get_remaining_trial_days();
186
 
187
  // User is in nudging period if remaining trial days are between minmum and maximum nudging days.
188
  $is_in_nudging_period = $remaining_trial_days >= $min_nudging_day && $remaining_trial_days <= $max_nudging_day ? true : false;
189
-
190
  // Start nudging the user if peried fall into nudging period.
191
  if ( $is_in_nudging_period ) {
192
  $current_nudging_day = 0;
193
-
194
  foreach ( $nudging_days as $day ) {
195
  if ( $remaining_trial_days <= $day ) {
196
  // Get current nudging day i.e. 1 or 3 or 5
@@ -211,7 +210,7 @@ class IG_ES_Trial {
211
 
212
  // Ceil function is used to round off to nearest upper limit integer, 4.1 would be 5.
213
  $date_diff_in_days = ceil( $date_diff_in_seconds / DAY_IN_SECONDS );
214
-
215
  // Check if current nudging day is after last dismissed date.
216
  if ( $current_nudging_day < $date_diff_in_days ) {
217
  $show_offer_notice = true;
@@ -219,7 +218,6 @@ class IG_ES_Trial {
219
  }
220
  }
221
  }
222
-
223
  }
224
 
225
  if ( $show_offer_notice ) {
7
 
8
  /**
9
  * The trial-specific functionality of the plugin.
 
10
  */
11
  class IG_ES_Trial {
12
 
28
 
29
  /**
30
  * Get class instance.
31
+ *
32
  * @since 4.6.2
33
  */
34
  public static function get_instance() {
42
 
43
  /**
44
  * Method to get trial period
45
+ *
46
  * @param string $period_in Period unit.
47
+ *
48
  * @return int Trial period in second.
49
+ *
50
  * @since 4.6.2
51
  */
52
  public function get_trial_period( $period_in = 'in_seconds' ) {
53
+
54
  $trial_period = 0;
55
+
56
  switch ( $period_in ) {
57
  case 'in_days':
58
  $trial_period = IG_ES_TRIAL_PERIOD_IN_DAYS;
64
 
65
  return $trial_period;
66
  }
67
+
68
  /**
69
  * Method to get total days since trial start date/time
70
+ *
71
  * @return int $trial_time_in_days Trial period passed in days.
72
+ *
73
  * @since 4.6.2
74
  */
75
  public function get_days_since_trial_started() {
76
+
77
  $current_time = time();
78
  $trial_time_in_days = 0;
79
  $trial_started_at = get_option( 'ig_es_trial_started_at' );
88
 
89
  /**
90
  * Method to get total remaining days in trial expiration.
91
+ *
92
  * @return int $remaining_trial_days Remaining trial days.
93
+ *
94
  * @since 4.6.2
95
  */
96
  public function get_remaining_trial_days() {
97
+
98
  $total_days_since_trial = $this->get_days_since_trial_started();
99
+ $trial_period_in_days = $this->get_trial_period( 'in_days' );
100
+ $remaining_trial_days = $trial_period_in_days - $total_days_since_trial;
101
 
102
  return $remaining_trial_days;
103
  }
104
+
105
  /**
106
  * Method to get trial expiry date
107
+ *
108
  * @param string $date_format Date formate
109
+ *
110
  * @return string $trial_expriy_date Trial expiry date.
111
+ *
112
  * @since 4.6.2
113
  */
114
  public function get_trial_expiry_date( $date_format = 'Y-m-d H:i:s' ) {
115
+
116
  $trial_expriy_date = '';
117
+ $trial_started_at = $this->get_trial_started_at();
118
+
119
  if ( ! empty( $trial_started_at ) ) {
120
  $trial_expires_at = $trial_started_at + $this->get_trial_period();
121
  $trial_expriy_date = gmdate( $date_format, $trial_expires_at );
123
 
124
  return $trial_expriy_date;
125
  }
126
+
127
  /**
128
  * Method to get trial started at timestamp.
129
+ *
130
  * @return int $trial_started_at Trial started at timestamp.
131
+ *
132
  * @since 4.6.2
133
  */
134
  public function get_trial_started_at() {
138
 
139
  /**
140
  * Method to show trial related notices to user.
141
+ *
142
  * @since 4.6.2
143
  */
144
  public function show_trial_notices() {
145
+
146
  // Don't show trial notices untill onboarding is completed.
147
  if ( ! IG_ES_Onboarding::is_onboarding_completed() ) {
148
  return;
149
  }
150
+
151
  $is_trial = ES()->is_trial();
152
  $is_premium = ES()->is_premium();
153
  $is_premium_installed = ES()->is_premium_installed();
159
  if ( ! $is_trial && ! $is_premium && 'es_dashboard' !== $current_page ) {
160
  // Check whether user has performed any action(accept/reject) on consent notice for trial. 'yes' if performed.
161
  $trial_consent_given = get_option( 'ig_es_trial_consent', 'no' );
162
+ if ( 'yes' !== $trial_consent_given ) {
163
  $show_trial_consent_notice = true;
164
  }
165
  }
169
  } else {
170
  ES_Admin_Notices::remove_notice( 'trial_consent' );
171
  }
172
+
173
  $show_offer_notice = false;
174
 
175
  // Add upgrade to premium nudging notice if user has opted for trial and is not a premium user and premium plugin is not installed on site and is not dashboard page.
181
  $max_nudging_day = max( $nudging_days );
182
 
183
  // Current day's number from start of trial.
184
+ $remaining_trial_days = ES()->trial->get_remaining_trial_days();
185
 
186
  // User is in nudging period if remaining trial days are between minmum and maximum nudging days.
187
  $is_in_nudging_period = $remaining_trial_days >= $min_nudging_day && $remaining_trial_days <= $max_nudging_day ? true : false;
188
+
189
  // Start nudging the user if peried fall into nudging period.
190
  if ( $is_in_nudging_period ) {
191
  $current_nudging_day = 0;
192
+
193
  foreach ( $nudging_days as $day ) {
194
  if ( $remaining_trial_days <= $day ) {
195
  // Get current nudging day i.e. 1 or 3 or 5
210
 
211
  // Ceil function is used to round off to nearest upper limit integer, 4.1 would be 5.
212
  $date_diff_in_days = ceil( $date_diff_in_seconds / DAY_IN_SECONDS );
213
+
214
  // Check if current nudging day is after last dismissed date.
215
  if ( $current_nudging_day < $date_diff_in_days ) {
216
  $show_offer_notice = true;
218
  }
219
  }
220
  }
 
221
  }
222
 
223
  if ( $show_offer_notice ) {
lite/includes/classes/class-ig-es-wc-session-tracker.php CHANGED
@@ -7,18 +7,17 @@ if ( ! defined( 'ABSPATH' ) ) {
7
  * Tracks logged out customers via cookies.
8
  *
9
  * @class IG_ES_WC_Session_Tracker
10
- *
11
  */
12
  class IG_ES_WC_Session_Tracker {
13
 
14
- /**
15
  * Tracking cookie expiry
16
- *
17
- * @var int (days)
18
  **/
19
  private static $tracking_cookie_expiry;
20
 
21
- /**
22
  * Tracking cookie name
23
  *
24
  * @var string - cookie name
@@ -27,11 +26,11 @@ class IG_ES_WC_Session_Tracker {
27
 
28
  /**
29
  * Tracking key
30
- *
31
- * @var string - This key WILL BE saved
32
  **/
33
  private static $tracking_key_to_set = '';
34
-
35
 
36
  /**
37
  * Returns true if a session tracking cookie has been set.
@@ -94,7 +93,7 @@ class IG_ES_WC_Session_Tracker {
94
 
95
  /**
96
  * Get current session key
97
- *
98
  * @return string|false
99
  */
100
  public static function get_current_tracking_key() {
@@ -117,7 +116,7 @@ class IG_ES_WC_Session_Tracker {
117
  * @return int
118
  */
119
  public static function get_detected_user_id() {
120
-
121
  if ( is_user_logged_in() ) {
122
  return get_current_user_id();
123
  }
@@ -141,7 +140,7 @@ class IG_ES_WC_Session_Tracker {
141
 
142
  global $woocommerce;
143
 
144
- //Can't look up the guest in this situation.
145
  if ( ! isset( $woocommerce->session ) ) {
146
  return false;
147
  }
@@ -164,15 +163,15 @@ class IG_ES_WC_Session_Tracker {
164
  *
165
  * - Registered user is logged in or remembered via cookie = bail
166
  * - Email matches existing customer
167
- * - Cookie customer exists
168
  * - Cookie and matched customer are the same = do nothing
169
- * - Cookie and matched customer are different = cookie must be changed, clear cart from previous key to avoid duplicates
170
- * - No cookie customer = Set new cookie to matched customer key
171
  * - Email is new
172
- * - Cookie customer exists
173
- * - Customer data is locked = create new customer, change cookie, clear cart from previous key to avoid duplicates
174
- * - Customer data is not locked = update customer email
175
- * - No cookie customer = Set new cookie to matched customer key
176
  *
177
  * @param string $new_email
178
  * @param string $language
@@ -180,7 +179,7 @@ class IG_ES_WC_Session_Tracker {
180
  * @return IG_ES_Customer|false
181
  */
182
  public static function set_session_by_captured_email( $new_email, $language = '' ) {
183
-
184
  if ( ! is_email( $new_email ) || headers_sent() || ! self::session_tracking_enabled() ) {
185
  // must have a valid email, be able to set cookies, have session tracking enabled
186
  return false;
@@ -241,7 +240,7 @@ class IG_ES_WC_Session_Tracker {
241
 
242
  // init the new customer tracking, also saves/updates the language
243
  // if ( $new_customer ) {
244
- // self::set_session_customer( $new_customer, $language );
245
  // }
246
 
247
  // update the stored cart
@@ -258,7 +257,7 @@ class IG_ES_WC_Session_Tracker {
258
  * @return Customer|false
259
  */
260
  public static function get_session_customer() {
261
-
262
  global $woocommerce;
263
 
264
  if ( is_user_logged_in() ) {
@@ -269,7 +268,7 @@ class IG_ES_WC_Session_Tracker {
269
  return false;
270
  }
271
 
272
- //Can't look up the customer in this situation.
273
  if ( ! isset( $woocommerce->session ) ) {
274
  return '';
275
  }
7
  * Tracks logged out customers via cookies.
8
  *
9
  * @class IG_ES_WC_Session_Tracker
 
10
  */
11
  class IG_ES_WC_Session_Tracker {
12
 
13
+ /**
14
  * Tracking cookie expiry
15
+ *
16
+ * @var int (days)
17
  **/
18
  private static $tracking_cookie_expiry;
19
 
20
+ /**
21
  * Tracking cookie name
22
  *
23
  * @var string - cookie name
26
 
27
  /**
28
  * Tracking key
29
+ *
30
+ * @var string - This key WILL BE saved
31
  **/
32
  private static $tracking_key_to_set = '';
33
+
34
 
35
  /**
36
  * Returns true if a session tracking cookie has been set.
93
 
94
  /**
95
  * Get current session key
96
+ *
97
  * @return string|false
98
  */
99
  public static function get_current_tracking_key() {
116
  * @return int
117
  */
118
  public static function get_detected_user_id() {
119
+
120
  if ( is_user_logged_in() ) {
121
  return get_current_user_id();
122
  }
140
 
141
  global $woocommerce;
142
 
143
+ // Can't look up the guest in this situation.
144
  if ( ! isset( $woocommerce->session ) ) {
145
  return false;
146
  }
163
  *
164
  * - Registered user is logged in or remembered via cookie = bail
165
  * - Email matches existing customer
166
+ * - Cookie customer exists
167
  * - Cookie and matched customer are the same = do nothing
168
+ * - Cookie and matched customer are different = cookie must be changed, clear cart from previous key to avoid duplicates
169
+ * - No cookie customer = Set new cookie to matched customer key
170
  * - Email is new
171
+ * - Cookie customer exists
172
+ * - Customer data is locked = create new customer, change cookie, clear cart from previous key to avoid duplicates
173
+ * - Customer data is not locked = update customer email
174
+ * - No cookie customer = Set new cookie to matched customer key
175
  *
176
  * @param string $new_email
177
  * @param string $language
179
  * @return IG_ES_Customer|false
180
  */
181
  public static function set_session_by_captured_email( $new_email, $language = '' ) {
182
+
183
  if ( ! is_email( $new_email ) || headers_sent() || ! self::session_tracking_enabled() ) {
184
  // must have a valid email, be able to set cookies, have session tracking enabled
185
  return false;
240
 
241
  // init the new customer tracking, also saves/updates the language
242
  // if ( $new_customer ) {
243
+ // self::set_session_customer( $new_customer, $language );
244
  // }
245
 
246
  // update the stored cart
257
  * @return Customer|false
258
  */
259
  public static function get_session_customer() {
260
+
261
  global $woocommerce;
262
 
263
  if ( is_user_logged_in() ) {
268
  return false;
269
  }
270
 
271
+ // Can't look up the customer in this situation.
272
  if ( ! isset( $woocommerce->session ) ) {
273
  return '';
274
  }
lite/includes/classes/ig-es-wc-cookies.php CHANGED
@@ -30,7 +30,7 @@ class IG_ES_WC_Cookies {
30
 
31
  /**
32
  * Gets a cookie
33
- *
34
  * @param $name
35
  * @return mixed
36
  */
30
 
31
  /**
32
  * Gets a cookie
33
+ *
34
  * @param $name
35
  * @return mixed
36
  */
lite/includes/compatibilities/elementor/actions/class-es-ig-form-action.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use Elementor\Controls_Manager;
4
+ use ElementorPro\Modules\Forms\Classes\Integration_Base;
5
+
6
+ if ( ! defined( 'ABSPATH' ) ) {
7
+ // Exit if accessed directly.
8
+ exit;
9
+ }
10
+
11
+ class Es_Form_Action extends Integration_Base {
12
+ /**
13
+ * Get the name for form action
14
+ *
15
+ * @return string
16
+ */
17
+ public function get_name() {
18
+ return 'email_subscribers';
19
+ }
20
+
21
+ /**
22
+ * Get the label of the action
23
+ *
24
+ * @return string
25
+ */
26
+ public function get_label() {
27
+ return __( 'Email Subscribers & Newsletter', 'email-subscribers' );
28
+ }
29
+
30
+ /**
31
+ * Register Email subscribers related settings
32
+ *
33
+ * @param \ElementorPro\Modules\Forms\Widgets\Form $form
34
+ */
35
+ public function register_settings_section( $form ) {
36
+ $form->start_controls_section(
37
+ 'section_email_subscribers',
38
+ array(
39
+ 'label' => __( 'Email Subscribers', 'email-subscribers' ),
40
+ 'condition' => array(
41
+ 'submit_actions' => $this->get_name(),
42
+ ),
43
+ )
44
+ );
45
+ $lists = ES()->lists_db->get_list_id_name_map();
46
+
47
+ $form->add_control(
48
+ 'email_subscribers_lists',
49
+ array(
50
+ 'label' => __( 'List', 'email-subscribers' ),
51
+ 'type' => Controls_Manager::SELECT2,
52
+ 'label_block' => true,
53
+ 'options' => $lists,
54
+ 'render_type' => 'none',
55
+ )
56
+ );
57
+
58
+ $this->register_fields_map_control( $form );
59
+
60
+ $form->end_controls_section();
61
+ }
62
+
63
+ public function on_export( $element ) {
64
+ unset( $element['email_subscribers_lists'] );
65
+
66
+ return $element;
67
+ }
68
+
69
+ /**
70
+ * Handle form submission
71
+ *
72
+ * @throws Exception
73
+ */
74
+ public function run( $record, $ajax_handler ) {
75
+ $settings = $record->get( 'form_settings' );
76
+ $subscriber = $this->map_fields( $record );
77
+ $ip_address = ig_es_get_request_data( 'ip_address' );
78
+ $subscription_list = isset( $settings['email_subscribers_lists'] ) && ! empty( $settings['email_subscribers_lists'] ) ? $settings['email_subscribers_lists'] : '';
79
+ if ( is_numeric( $subscription_list ) ) {
80
+ $lists = ES()->lists_db->get_lists_by_id( $subscription_list );
81
+ if ( ! empty( $lists ) ) {
82
+ $list_hash = ! empty( $lists[0]['hash'] ) ? $lists[0]['hash'] : '';
83
+ if ( ! empty( $list_hash ) ) {
84
+ $subscriber['esfpx_lists'] = array( $list_hash );
85
+ }
86
+ }
87
+ }
88
+ $subscriber['esfpx_ip_address'] = $ip_address;
89
+ $subscriber['form_type'] = 'external';
90
+ $subscriber['esfpx_es_hp_email'] = '';
91
+ // This constant is defined to return the response form process_request method
92
+ // Because process_request using wp_send_json function to return response,
93
+ defined( 'IG_ES_RETURN_HANDLE_RESPONSE' ) || define( 'IG_ES_RETURN_HANDLE_RESPONSE', true );
94
+ $es = new ES_Handle_Subscription();
95
+ $response = $es->process_request( $subscriber );
96
+ if ( 'ERROR' === $response['status'] ) {
97
+ // If there any error just return response
98
+ wp_send_json_error( array( 'message' => $response['message_text'] ) );
99
+ }
100
+ // No need to process success response
101
+ }
102
+
103
+ /**
104
+ * Map Elemntor's form fields with Email subscriber's fields on frontend form submission
105
+ *
106
+ * @param ElementorPro\Modules\Forms\Classes\Form_Record $record
107
+ *
108
+ * @return array
109
+ */
110
+ private function map_fields( $record ) {
111
+ $settings = $record->get( 'form_settings' );
112
+ $fields = $record->get( 'fields' );
113
+
114
+ $subscriber = array();
115
+
116
+ foreach ( $settings['email_subscribers_fields_map'] as $map_item ) {
117
+ if ( empty( $fields[ $map_item['local_id'] ]['value'] ) ) {
118
+ continue;
119
+ }
120
+
121
+ $subscriber[ $map_item['remote_id'] ] = $fields[ $map_item['local_id'] ]['value'];
122
+ }
123
+
124
+ return $subscriber;
125
+ }
126
+
127
+ /**
128
+ * Email subscribers fields that need to map with Elementor form fields
129
+ *
130
+ * @return array
131
+ */
132
+ protected function get_fields_map_control_options() {
133
+ $email_subscribers_fields = array(
134
+ array(
135
+ 'remote_id' => 'esfpx_name',
136
+ 'remote_label' => __( 'Name', 'email-subscribers' ),
137
+ 'remote_type' => 'text',
138
+ ),
139
+ array(
140
+ 'remote_id' => 'esfpx_email',
141
+ 'remote_label' => __( 'Email', 'email-subscribers' ),
142
+ 'remote_type' => 'email',
143
+ 'remote_required' => true,
144
+ ),
145
+ );
146
+
147
+ apply_filters( 'ig_es_compatability_elementor_get_fields_map_control_options', $email_subscribers_fields );
148
+
149
+ return array(
150
+ 'default' => $email_subscribers_fields,
151
+ 'condition' => array(
152
+ 'email_subscribers_lists!' => '',
153
+ ),
154
+ );
155
+ }
156
+ }
lite/includes/compatibilities/elementor/class-ig-es-compatibility.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ // Exit if accessed directly.
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * Main Elementor Form compatability Class
9
+ */
10
+ final class ES_Compatibility_Elementor {
11
+
12
+ /**
13
+ * Constructor
14
+ */
15
+ public function __construct() {
16
+ // Initialize the custom block feature.
17
+ add_action( 'elementor_pro/forms/register_action', array( $this, 'register_for_action' ) );
18
+ }
19
+
20
+ /**
21
+ * Register form actions on Elementor_Pro/Forms/Register_Action
22
+ *
23
+ * @param $forms_module \ElementorPro\Modules\Forms\Module
24
+ */
25
+ public function register_for_action( $forms_module ) {
26
+ require_once 'actions/class-es-ig-form-action.php';
27
+ $forms_module->add_form_action( 'email_subscribers', new Es_Form_Action() );
28
+ }
29
+
30
+ }
31
+
32
+ new ES_Compatibility_Elementor();
lite/includes/db/class-es-db-actions.php CHANGED
@@ -10,7 +10,6 @@ class ES_DB_Actions extends ES_DB {
10
  *
11
  * @since 4.2.1
12
  * @var $table_name
13
- *
14
  */
15
  public $table_name;
16
 
@@ -19,7 +18,6 @@ class ES_DB_Actions extends ES_DB {
19
  *
20
  * @since 4.2.1
21
  * @var $version
22
- *
23
  */
24
  public $version;
25
 
@@ -28,7 +26,6 @@ class ES_DB_Actions extends ES_DB {
28
  *
29
  * @since 4.2.1
30
  * @var $primary_key
31
- *
32
  */
33
  public $primary_key;
34
 
@@ -62,7 +59,7 @@ class ES_DB_Actions extends ES_DB {
62
  'count' => '%d',
63
  'link_id' => '%d',
64
  'list_id' => '%d',
65
- 'ip' => '%s',
66
  'country' => '%s',
67
  'device' => '%s',
68
  'browser' => '%s',
@@ -87,14 +84,14 @@ class ES_DB_Actions extends ES_DB {
87
  'count' => 0,
88
  'link_id' => 0,
89
  'list_id' => 0,
90
- 'ip' => '',
91
  'country' => '',
92
  'device' => '',
93
  'browser' => '',
94
  'email_client' => '',
95
  'os' => '',
96
  'created_at' => ig_es_get_current_gmt_timestamp(),
97
- 'updated_at' => ig_es_get_current_gmt_timestamp()
98
  );
99
  }
100
 
@@ -111,13 +108,13 @@ class ES_DB_Actions extends ES_DB {
111
  public function add( $args, $explicit = true ) {
112
 
113
  global $wpbd;
114
-
115
  $ig_actions_table = IG_ACTIONS_TABLE;
116
-
117
  $args_keys = array_keys( $args );
118
-
119
  $args_keys_str = implode( ', ', $args_keys );
120
-
121
  $sql = "INSERT INTO $ig_actions_table ($args_keys_str)";
122
 
123
  $args_values_array = array();
@@ -138,17 +135,16 @@ class ES_DB_Actions extends ES_DB {
138
  $args_values_array[] = $this->prepare_for_in_query( $args_values );
139
  }
140
 
141
-
142
  $sql .= ' VALUES ( ' . implode( '), (', $args_values_array ) . ' )';
143
  $sql .= ' ON DUPLICATE KEY UPDATE';
144
  $sql .= ( $explicit ) ? $wpbd->prepare( ' created_at = created_at, count = count+1, updated_at = %d, ip = %s, country = %s, browser = %s, device = %s, os = %s, email_client = %s', ig_es_get_current_gmt_timestamp(), $args['ip'], $args['country'], $args['browser'], $args['device'], $args['os'], $args['email_client'] ) : ' count = values(count)';
145
-
146
  $result = $wpbd->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
147
-
148
  if ( false !== $result ) {
149
  return true;
150
  }
151
-
152
  return false;
153
  }
154
 
@@ -165,14 +161,14 @@ class ES_DB_Actions extends ES_DB {
165
  global $wpdb;
166
 
167
  $args = array(
168
- IG_LINK_CLICK
169
  );
170
 
171
  $total_contacts_clicked = 0;
172
  if ( $distinct ) {
173
  if ( 0 != $days ) {
174
- $days = esc_sql( $days );
175
- $args[] = $days;
176
  $total_contacts_clicked = $wpdb->get_var(
177
  $wpdb->prepare(
178
  "SELECT COUNT(DISTINCT(`contact_id`)) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
@@ -189,8 +185,8 @@ class ES_DB_Actions extends ES_DB {
189
  }
190
  } else {
191
  if ( 0 != $days ) {
192
- $days = esc_sql( $days );
193
- $args[] = $days;
194
  $total_contacts_clicked = $wpdb->get_var(
195
  $wpdb->prepare(
196
  "SELECT COUNT(`contact_id`) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
@@ -216,21 +212,19 @@ class ES_DB_Actions extends ES_DB {
216
  * @param int $days
217
  *
218
  * @return string|null
219
- *
220
- *
221
  */
222
  public function get_total_contact_lost( $days = 0, $distinct = true ) {
223
  global $wpdb;
224
 
225
  $args = array(
226
- IG_CONTACT_UNSUBSCRIBE
227
  );
228
 
229
  $total_emails_unsubscribed = 0;
230
  if ( $distinct ) {
231
  if ( 0 != $days ) {
232
- $days = esc_sql( $days );
233
- $args[] = $days;
234
  $total_emails_unsubscribed = $wpdb->get_var(
235
  $wpdb->prepare(
236
  "SELECT COUNT(DISTINCT(`contact_id`)) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
@@ -247,8 +241,8 @@ class ES_DB_Actions extends ES_DB {
247
  }
248
  } else {
249
  if ( 0 != $days ) {
250
- $days = esc_sql( $days );
251
- $args[] = $days;
252
  $total_emails_unsubscribed = $wpdb->get_var(
253
  $wpdb->prepare(
254
  "SELECT COUNT(`contact_id`) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
@@ -283,14 +277,14 @@ class ES_DB_Actions extends ES_DB {
283
  global $wpdb;
284
 
285
  $args = array(
286
- IG_MESSAGE_OPEN
287
  );
288
 
289
  $total_emails_opened = 0;
290
  if ( $distinct ) {
291
  if ( 0 != $days ) {
292
- $days = esc_sql( $days );
293
- $args[] = $days;
294
  $total_emails_opened = $wpdb->get_var(
295
  $wpdb->prepare(
296
  "SELECT COUNT(DISTINCT(`contact_id`)) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
@@ -307,8 +301,8 @@ class ES_DB_Actions extends ES_DB {
307
  }
308
  } else {
309
  if ( 0 != $days ) {
310
- $days = esc_sql( $days );
311
- $args[] = $days;
312
  $total_emails_opened = $wpdb->get_var(
313
  $wpdb->prepare(
314
  "SELECT COUNT(`contact_id`) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
@@ -341,14 +335,14 @@ class ES_DB_Actions extends ES_DB {
341
  global $wpdb;
342
 
343
  $args = array(
344
- IG_MESSAGE_SENT
345
  );
346
 
347
  $total_emails_sent = 0;
348
  if ( $distinct ) {
349
  if ( 0 != $days ) {
350
- $days = esc_sql( $days );
351
- $args[] = $days;
352
  $total_emails_sent = $wpdb->get_var(
353
  $wpdb->prepare(
354
  "SELECT COUNT(DISTINCT(`contact_id`)) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
@@ -365,8 +359,8 @@ class ES_DB_Actions extends ES_DB {
365
  }
366
  } else {
367
  if ( 0 != $days ) {
368
- $days = esc_sql( $days );
369
- $args[] = $days;
370
  $total_emails_sent = $wpdb->get_var(
371
  $wpdb->prepare(
372
  "SELECT COUNT(`contact_id`) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
@@ -387,7 +381,7 @@ class ES_DB_Actions extends ES_DB {
387
  }
388
 
389
  /**
390
- * Get contact count based on campaign_id and type
391
  *
392
  * @return string|null
393
  *
@@ -397,9 +391,9 @@ class ES_DB_Actions extends ES_DB {
397
  global $wpbd;
398
 
399
  $args = array();
400
-
401
  $args[] = $campaign_id;
402
- $args[] = $message_id;
403
  $args[] = $type;
404
 
405
  $count = 0;
@@ -415,7 +409,7 @@ class ES_DB_Actions extends ES_DB {
415
  );
416
  }
417
 
418
- $cache_key = ES_Cache::generate_key( $query );
419
  $exists_in_cache = ES_Cache::is_exists( $cache_key, 'query' );
420
  if ( ! $exists_in_cache ) {
421
  $count = $wpbd->get_var(
@@ -448,13 +442,13 @@ class ES_DB_Actions extends ES_DB {
448
 
449
  $contact_ids_str = implode( ',', $contact_ids );
450
 
451
- $result = $wpbd->get_results( $wpbd->prepare( "SELECT contact_id, MAX(created_at) as last_opened_at FROM {$wpbd->prefix}ig_actions WHERE contact_id IN ({$contact_ids_str}) AND type = %d GROUP BY contact_id", IG_MESSAGE_OPEN ), ARRAY_A );
452
-
453
  if ( $filter ) {
454
- $last_opened_at = array_column($result, 'last_opened_at', 'contact_id');
455
  foreach ( $last_opened_at as $contact_id => $timestamp ) {
456
- $convert_date_format = get_option( 'date_format' );
457
- $convert_time_format = get_option( 'time_format' );
458
  $last_opened_at[ $contact_id ] = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $timestamp ), $convert_date_format . ' ' . $convert_time_format );
459
  }
460
  return $last_opened_at;
10
  *
11
  * @since 4.2.1
12
  * @var $table_name
 
13
  */
14
  public $table_name;
15
 
18
  *
19
  * @since 4.2.1
20
  * @var $version
 
21
  */
22
  public $version;
23
 
26
  *
27
  * @since 4.2.1
28
  * @var $primary_key
 
29
  */
30
  public $primary_key;
31
 
59
  'count' => '%d',
60
  'link_id' => '%d',
61
  'list_id' => '%d',
62
+ 'ip' => '%s',
63
  'country' => '%s',
64
  'device' => '%s',
65
  'browser' => '%s',
84
  'count' => 0,
85
  'link_id' => 0,
86
  'list_id' => 0,
87
+ 'ip' => '',
88
  'country' => '',
89
  'device' => '',
90
  'browser' => '',
91
  'email_client' => '',
92
  'os' => '',
93
  'created_at' => ig_es_get_current_gmt_timestamp(),
94
+ 'updated_at' => ig_es_get_current_gmt_timestamp(),
95
  );
96
  }
97
 
108
  public function add( $args, $explicit = true ) {
109
 
110
  global $wpbd;
111
+
112
  $ig_actions_table = IG_ACTIONS_TABLE;
113
+
114
  $args_keys = array_keys( $args );
115
+
116
  $args_keys_str = implode( ', ', $args_keys );
117
+
118
  $sql = "INSERT INTO $ig_actions_table ($args_keys_str)";
119
 
120
  $args_values_array = array();
135
  $args_values_array[] = $this->prepare_for_in_query( $args_values );
136
  }
137
 
 
138
  $sql .= ' VALUES ( ' . implode( '), (', $args_values_array ) . ' )';
139
  $sql .= ' ON DUPLICATE KEY UPDATE';
140
  $sql .= ( $explicit ) ? $wpbd->prepare( ' created_at = created_at, count = count+1, updated_at = %d, ip = %s, country = %s, browser = %s, device = %s, os = %s, email_client = %s', ig_es_get_current_gmt_timestamp(), $args['ip'], $args['country'], $args['browser'], $args['device'], $args['os'], $args['email_client'] ) : ' count = values(count)';
141
+
142
  $result = $wpbd->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
143
+
144
  if ( false !== $result ) {
145
  return true;
146
  }
147
+
148
  return false;
149
  }
150
 
161
  global $wpdb;
162
 
163
  $args = array(
164
+ IG_LINK_CLICK,
165
  );
166
 
167
  $total_contacts_clicked = 0;
168
  if ( $distinct ) {
169
  if ( 0 != $days ) {
170
+ $days = esc_sql( $days );
171
+ $args[] = $days;
172
  $total_contacts_clicked = $wpdb->get_var(
173
  $wpdb->prepare(
174
  "SELECT COUNT(DISTINCT(`contact_id`)) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
185
  }
186
  } else {
187
  if ( 0 != $days ) {
188
+ $days = esc_sql( $days );
189
+ $args[] = $days;
190
  $total_contacts_clicked = $wpdb->get_var(
191
  $wpdb->prepare(
192
  "SELECT COUNT(`contact_id`) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
212
  * @param int $days
213
  *
214
  * @return string|null
 
 
215
  */
216
  public function get_total_contact_lost( $days = 0, $distinct = true ) {
217
  global $wpdb;
218
 
219
  $args = array(
220
+ IG_CONTACT_UNSUBSCRIBE,
221
  );
222
 
223
  $total_emails_unsubscribed = 0;
224
  if ( $distinct ) {
225
  if ( 0 != $days ) {
226
+ $days = esc_sql( $days );
227
+ $args[] = $days;
228
  $total_emails_unsubscribed = $wpdb->get_var(
229
  $wpdb->prepare(
230
  "SELECT COUNT(DISTINCT(`contact_id`)) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
241
  }
242
  } else {
243
  if ( 0 != $days ) {
244
+ $days = esc_sql( $days );
245
+ $args[] = $days;
246
  $total_emails_unsubscribed = $wpdb->get_var(
247
  $wpdb->prepare(
248
  "SELECT COUNT(`contact_id`) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
277
  global $wpdb;
278
 
279
  $args = array(
280
+ IG_MESSAGE_OPEN,
281
  );
282
 
283
  $total_emails_opened = 0;
284
  if ( $distinct ) {
285
  if ( 0 != $days ) {
286
+ $days = esc_sql( $days );
287
+ $args[] = $days;
288
  $total_emails_opened = $wpdb->get_var(
289
  $wpdb->prepare(
290
  "SELECT COUNT(DISTINCT(`contact_id`)) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
301
  }
302
  } else {
303
  if ( 0 != $days ) {
304
+ $days = esc_sql( $days );
305
+ $args[] = $days;
306
  $total_emails_opened = $wpdb->get_var(
307
  $wpdb->prepare(
308
  "SELECT COUNT(`contact_id`) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
335
  global $wpdb;
336
 
337
  $args = array(
338
+ IG_MESSAGE_SENT,
339
  );
340
 
341
  $total_emails_sent = 0;
342
  if ( $distinct ) {
343
  if ( 0 != $days ) {
344
+ $days = esc_sql( $days );
345
+ $args[] = $days;
346
  $total_emails_sent = $wpdb->get_var(
347
  $wpdb->prepare(
348
  "SELECT COUNT(DISTINCT(`contact_id`)) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
359
  }
360
  } else {
361
  if ( 0 != $days ) {
362
+ $days = esc_sql( $days );
363
+ $args[] = $days;
364
  $total_emails_sent = $wpdb->get_var(
365
  $wpdb->prepare(
366
  "SELECT COUNT(`contact_id`) FROM {$wpdb->prefix}ig_actions WHERE `type` = %d AND created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL %d DAY))",
381
  }
382
 
383
  /**
384
+ * Get contact count based on campaign_id and type
385
  *
386
  * @return string|null
387
  *
391
  global $wpbd;
392
 
393
  $args = array();
394
+
395
  $args[] = $campaign_id;
396
+ $args[] = $message_id;
397
  $args[] = $type;
398
 
399
  $count = 0;
409
  );
410
  }
411
 
412
+ $cache_key = ES_Cache::generate_key( $query );
413
  $exists_in_cache = ES_Cache::is_exists( $cache_key, 'query' );
414
  if ( ! $exists_in_cache ) {
415
  $count = $wpbd->get_var(
442
 
443
  $contact_ids_str = implode( ',', $contact_ids );
444
 
445
+ $result = $wpbd->get_results( $wpbd->prepare( "SELECT contact_id, MAX(created_at) as last_opened_at FROM {$wpbd->prefix}ig_actions WHERE contact_id IN ({$contact_ids_str}) AND type = %d GROUP BY contact_id", IG_MESSAGE_OPEN ), ARRAY_A );
446
+
447
  if ( $filter ) {
448
+ $last_opened_at = array_column( $result, 'last_opened_at', 'contact_id' );
449
  foreach ( $last_opened_at as $contact_id => $timestamp ) {
450
+ $convert_date_format = get_option( 'date_format' );
451
+ $convert_time_format = get_option( 'time_format' );
452
  $last_opened_at[ $contact_id ] = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $timestamp ), $convert_date_format . ' ' . $convert_time_format );
453
  }
454
  return $last_opened_at;
lite/includes/db/class-es-db-blocked-emails.php CHANGED
@@ -21,7 +21,6 @@ class ES_DB_Blocked_Emails extends ES_DB {
21
  * @since 4.2.2
22
  *
23
  * @var $version
24
- *
25
  */
26
  public $version;
27
 
@@ -31,7 +30,6 @@ class ES_DB_Blocked_Emails extends ES_DB {
31
  * @since 4.2.2
32
  *
33
  * @var $primary_key
34
- *
35
  */
36
  public $primary_key;
37
 
21
  * @since 4.2.2
22
  *
23
  * @var $version
 
24
  */
25
  public $version;
26
 
30
  * @since 4.2.2
31
  *
32
  * @var $primary_key
 
33
  */
34
  public $primary_key;
35
 
lite/includes/db/class-es-db-campaigns.php CHANGED
@@ -15,7 +15,6 @@ class ES_DB_Campaigns extends ES_DB {
15
  *
16
  * @since 4.2.1
17
  * @var string $table_name
18
- *
19
  */
20
  public $table_name;
21
 
@@ -24,7 +23,6 @@ class ES_DB_Campaigns extends ES_DB {
24
  *
25
  * @since 4.2.1
26
  * @var string $version
27
- *
28
  */
29
  public $version;
30
 
@@ -33,7 +31,6 @@ class ES_DB_Campaigns extends ES_DB {
33
  *
34
  * @since 4.2.1
35
  * @var string
36
- *
37
  */
38
  public $primary_key;
39
 
@@ -48,7 +45,6 @@ class ES_DB_Campaigns extends ES_DB {
48
 
49
  $this->version = '1.0';
50
 
51
-
52
  }
53
 
54
  /**
@@ -77,7 +73,7 @@ class ES_DB_Campaigns extends ES_DB {
77
  'created_at' => '%s',
78
  'updated_at' => '%s',
79
  'deleted_at' => '%s',
80
- 'meta' => '%s'
81
  );
82
  }
83
 
@@ -110,7 +106,7 @@ class ES_DB_Campaigns extends ES_DB {
110
  'created_at' => ig_get_current_date_time(),
111
  'updated_at' => null,
112
  'deleted_at' => null,
113
- 'meta' => null
114
  );
115
  }
116
 
@@ -199,8 +195,8 @@ class ES_DB_Campaigns extends ES_DB {
199
 
200
  for ( $i = 0; $i < $total_batches; $i ++ ) {
201
  $batch_start = $i * $batch_size;
202
- //$query = 'SELECT * FROM ' . EMAIL_SUBSCRIBERS_NOTIFICATION_TABLE . " LIMIT {$batch_start}, {$batch_size}";
203
- //$notifications = $wpbd->get_results( $query, ARRAY_A ); // WPCS: cache ok, DB call ok, unprepared SQL ok.
204
  $notifications = $wpbd->get_results( $wpbd->prepare( "SELECT * FROM {$wpbd->prefix}es_notification LIMIT %d, %d", $batch_start, $batch_size ), ARRAY_A );
205
  if ( count( $notifications ) > 0 ) {
206
  foreach ( $notifications as $key => $notification ) {
@@ -248,7 +244,7 @@ class ES_DB_Campaigns extends ES_DB {
248
  }
249
  }
250
 
251
- //Do Batach Insert
252
  $values = array();
253
  $place_holders = array();
254
  $columns = $this->get_columns();
@@ -283,20 +279,20 @@ class ES_DB_Campaigns extends ES_DB {
283
  */
284
  public function migrate_newsletters() {
285
  global $wpdb;
286
-
287
  // Check if es_sentdetails table exists or not.
288
  if ( $this->table_exists( $wpdb->prefix . 'es_sentdetails' ) ) {
289
  $from_name = ES_Common::get_ig_option( 'from_name' );
290
  $from_email = ES_Common::get_ig_option( 'from_email' );
291
-
292
  $total = $wpdb->get_var( $wpdb->prepare( "SELECT count(*) as total FROM {$wpdb->prefix}es_sentdetails WHERE es_sent_source = %s", 'Newsletter' ) );
293
-
294
  if ( $total > 0 ) {
295
-
296
  $list_is_name_map = ES()->lists_db->get_list_id_name_map( '', true );
297
  $batch_size = IG_DEFAULT_BATCH_SIZE;
298
  $total_batches = ceil( $total / $batch_size );
299
-
300
  $values = array();
301
  $place_holders = array();
302
  $columns = $this->get_columns();
@@ -304,9 +300,9 @@ class ES_DB_Campaigns extends ES_DB {
304
  $fields = array_keys( $columns );
305
  for ( $i = 0; $i <= $total_batches; $i ++ ) {
306
  $batch_start = $i * $batch_size;
307
-
308
  $newsletters = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}es_sentdetails WHERE es_sent_source = %s LIMIT %d, %d", 'Newsletter', $batch_start, $batch_size ), ARRAY_A );
309
-
310
  if ( count( $newsletters ) > 0 ) {
311
  $campaign_data = array();
312
  $values = array();
@@ -322,18 +318,18 @@ class ES_DB_Campaigns extends ES_DB {
322
  $campaign_data['list_ids'] = ( ! empty( $newsletter['es_note_group'] ) && ! empty( $list_is_name_map[ $newsletter['es_note_group'] ] ) ) ? $list_is_name_map[ $newsletter['es_note_group'] ] : 0;
323
  $campaign_data['status'] = 1;
324
  $campaign_data['created_at'] = $newsletter['es_sent_starttime'];
325
-
326
  $campaign_data = wp_parse_args( $campaign_data, $this->get_column_defaults() );
327
-
328
  $formats = array();
329
  foreach ( $columns as $column => $format ) {
330
  $values[] = $campaign_data[ $column ];
331
  $formats[] = $format;
332
  }
333
-
334
  $place_holders[] = '( ' . implode( ', ', $formats ) . ' )';
335
  }
336
-
337
  ES_DB::do_insert( IG_CAMPAIGNS_TABLE, $fields, $place_holders, $values );
338
  }
339
  }
@@ -364,10 +360,8 @@ class ES_DB_Campaigns extends ES_DB {
364
  break;
365
  }
366
  }
367
-
368
  }
369
  }
370
-
371
  }
372
 
373
  if ( ! empty( $data_to_update ) ) {
@@ -554,7 +548,7 @@ class ES_DB_Campaigns extends ES_DB {
554
  /**
555
  * Update meta value
556
  *
557
- * @param int $campaign_id
558
  * @param array $meta_data
559
  *
560
  * @return bool|false|int
@@ -580,7 +574,6 @@ class ES_DB_Campaigns extends ES_DB {
580
 
581
  $update = $this->save_campaign( $campaign, $campaign_id );
582
 
583
-
584
  }
585
  }
586
  }
@@ -664,7 +657,7 @@ class ES_DB_Campaigns extends ES_DB {
664
  $total_categories = count( $categories );
665
  if ( $total_categories > 0 ) {
666
  for ( $i = 0; $i < $total_categories; $i ++ ) {
667
- if ( 0 === $i) {
668
  $where .= ' and (';
669
  } else {
670
  $where .= ' or';
@@ -673,13 +666,13 @@ class ES_DB_Campaigns extends ES_DB {
673
  $category_str = ES_Common::prepare_category_string( $categories[ $i ]->term_id );
674
 
675
  $where .= " categories LIKE '%" . $category_str . "%'";
676
- if ( ( $total_categories - 1 ) === $i ) {
677
  $where .= " OR categories LIKE '%all%'";
678
  $where .= ") AND categories NOT LIKE '%none%'";
679
  }
680
  }
681
  } else {
682
- //no categories fround for post
683
  return $campaigns;
684
  }
685
  } else {
@@ -697,7 +690,7 @@ class ES_DB_Campaigns extends ES_DB {
697
  /**
698
  * Method to update campaign status
699
  *
700
- * @param array $campaign_ids Campaign IDs.
701
  * @param integer $status New status.
702
  *
703
  * @return bool $updated Update status
@@ -722,10 +715,10 @@ class ES_DB_Campaigns extends ES_DB {
722
 
723
  if ( ! empty( $id_str ) ) {
724
 
725
- $updated = $wpbd->query( $wpbd->prepare("UPDATE {$wpbd->prefix}ig_campaigns SET status = %d WHERE id IN({$id_str})", $status ) );
726
 
727
- //Changing status of child campaigns along with its parent campaign id
728
- $wpbd->query( $wpbd->prepare("UPDATE {$wpbd->prefix}ig_campaigns SET status = %d WHERE parent_id IN({$id_str})", $status ) );
729
  }
730
 
731
  return $updated;
@@ -742,20 +735,20 @@ class ES_DB_Campaigns extends ES_DB {
742
  public function duplicate_campaign( $id = null ) {
743
 
744
  if ( ! empty( $id ) ) {
745
-
746
- $campaign = $this->get( $id );
747
  $campaign['status'] = IG_ES_CAMPAIGN_STATUS_IN_ACTIVE;
748
- $campaign['name'] = __( 'Copy', 'email-subscribers' ) . ' - ' . $campaign['name'];
749
 
750
  if ( 'newsletter' === $campaign['type'] ) {
751
- $campaign['subject'] = __( 'Copy', 'email-subscribers' ) . ' - ' . $campaign['subject'];
752
  }
753
- $campaign_id = $campaign['id'];
754
  unset( $campaign['id'] );
755
  unset( $campaign['created_at'] );
756
 
757
  $duplicate_campaign_id = $this->save_campaign( $campaign );
758
-
759
  if ( 'sequence' === $campaign['type'] ) {
760
  $sequence_campaigns = $this->get_campaign_by_parent_id( $campaign_id );
761
 
@@ -771,11 +764,11 @@ class ES_DB_Campaigns extends ES_DB {
771
 
772
  /**
773
  * Get all campaigns based on passed arguements
774
- *
775
  * @param array $args Campaing arguements
776
- *
777
  * @return array Array of campaigns
778
- *
779
  * @since 4.6.11
780
  */
781
  public function get_all_campaigns( $args = array() ) {
@@ -786,25 +779,25 @@ class ES_DB_Campaigns extends ES_DB {
786
  if ( ! empty( $args['include_types'] ) ) {
787
  $type_count = count( $args['include_types'] );
788
  $type_placeholders = array_fill( 0, $type_count, '%s' );
789
- $where .= $wpbd->prepare( 'type IN( ' . implode( ',', $type_placeholders ) . ' )', $args['include_types'] );
790
  }
791
 
792
  if ( ! empty( $args['exclude_types'] ) ) {
793
  $type_count = count( $args['exclude_types'] );
794
  $type_placeholders = array_fill( 0, $type_count, '%s' );
795
- $where .= $wpbd->prepare( 'type NOT IN( ' . implode( ',', $type_placeholders ) . ' )', $args['exclude_types'] );
796
  }
797
 
798
  if ( ! empty( $args['status'] ) ) {
799
  $status_count = count( $args['status'] );
800
  $status_placeholders = array_fill( 0, $status_count, '%d' );
801
- $where .= $wpbd->prepare( ' AND status IN( ' . implode( ',', $status_placeholders ) . ' )', $args['status'] );
802
  }
803
-
804
  if ( ! empty( $args['campaigns_not_in'] ) ) {
805
  $ids_count = count( $args['campaigns_not_in'] );
806
  $ids_placeholders = array_fill( 0, $ids_count, '%d' );
807
- $where .= $wpbd->prepare( ' AND id NOT IN( ' . implode( ',', $ids_placeholders ) . ' )', $args['campaigns_not_in'] );
808
  }
809
 
810
  return $this->get_by_conditions( $where );
@@ -812,11 +805,11 @@ class ES_DB_Campaigns extends ES_DB {
812
 
813
  /**
814
  * Get selected lists ids in the campaign
815
- *
816
  * @param int $campaign_id
817
- *
818
  * @return array $list_ids
819
- *
820
  * @since 4.7.6
821
  */
822
  public function get_list_ids( $campaign_id ) {
@@ -835,14 +828,14 @@ class ES_DB_Campaigns extends ES_DB {
835
  if ( ! empty( $campaign['list_ids'] ) ) {
836
  $list_ids = explode( ',', $campaign['list_ids'] );
837
  }
838
-
839
  $campaign_meta = maybe_unserialize( $campaign['meta'] );
840
- $conditions = isset( $campaign_meta['list_conditions'] ) ? $campaign_meta['list_conditions']: array();
841
  if ( ! empty( $conditions ) ) {
842
  foreach ( $conditions as $i => $condition_group ) {
843
  if ( ! empty( $condition_group ) ) {
844
  foreach ( $condition_group as $j => $condition ) {
845
- $condition_field = isset ( $condition['field'] ) ? $condition['field'] : '';
846
  if ( '_lists__in' === $condition_field ) {
847
  if ( ! empty( $condition['value'] ) && is_array( $condition['value'] ) ) {
848
  $list_ids = array_merge( $list_ids, $condition['value'] );
15
  *
16
  * @since 4.2.1
17
  * @var string $table_name
 
18
  */
19
  public $table_name;
20
 
23
  *
24
  * @since 4.2.1
25
  * @var string $version
 
26
  */
27
  public $version;
28
 
31
  *
32
  * @since 4.2.1
33
  * @var string
 
34
  */
35
  public $primary_key;
36
 
45
 
46
  $this->version = '1.0';
47
 
 
48
  }
49
 
50
  /**
73
  'created_at' => '%s',
74
  'updated_at' => '%s',
75
  'deleted_at' => '%s',
76
+ 'meta' => '%s',
77
  );
78
  }
79
 
106
  'created_at' => ig_get_current_date_time(),
107
  'updated_at' => null,
108
  'deleted_at' => null,
109
+ 'meta' => null,
110
  );
111
  }
112
 
195
 
196
  for ( $i = 0; $i < $total_batches; $i ++ ) {
197
  $batch_start = $i * $batch_size;
198
+ // $query = 'SELECT * FROM ' . EMAIL_SUBSCRIBERS_NOTIFICATION_TABLE . " LIMIT {$batch_start}, {$batch_size}";
199
+ // $notifications = $wpbd->get_results( $query, ARRAY_A ); // WPCS: cache ok, DB call ok, unprepared SQL ok.
200
  $notifications = $wpbd->get_results( $wpbd->prepare( "SELECT * FROM {$wpbd->prefix}es_notification LIMIT %d, %d", $batch_start, $batch_size ), ARRAY_A );
201
  if ( count( $notifications ) > 0 ) {
202
  foreach ( $notifications as $key => $notification ) {
244
  }
245
  }
246
 
247
+ // Do Batach Insert
248
  $values = array();
249
  $place_holders = array();
250
  $columns = $this->get_columns();
279
  */
280
  public function migrate_newsletters() {
281
  global $wpdb;
282
+
283
  // Check if es_sentdetails table exists or not.
284
  if ( $this->table_exists( $wpdb->prefix . 'es_sentdetails' ) ) {
285
  $from_name = ES_Common::get_ig_option( 'from_name' );
286
  $from_email = ES_Common::get_ig_option( 'from_email' );
287
+
288
  $total = $wpdb->get_var( $wpdb->prepare( "SELECT count(*) as total FROM {$wpdb->prefix}es_sentdetails WHERE es_sent_source = %s", 'Newsletter' ) );
289
+
290
  if ( $total > 0 ) {
291
+
292
  $list_is_name_map = ES()->lists_db->get_list_id_name_map( '', true );
293
  $batch_size = IG_DEFAULT_BATCH_SIZE;
294
  $total_batches = ceil( $total / $batch_size );
295
+
296
  $values = array();
297
  $place_holders = array();
298
  $columns = $this->get_columns();
300
  $fields = array_keys( $columns );
301
  for ( $i = 0; $i <= $total_batches; $i ++ ) {
302
  $batch_start = $i * $batch_size;
303
+
304
  $newsletters = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}es_sentdetails WHERE es_sent_source = %s LIMIT %d, %d", 'Newsletter', $batch_start, $batch_size ), ARRAY_A );
305
+
306
  if ( count( $newsletters ) > 0 ) {
307
  $campaign_data = array();
308
  $values = array();
318
  $campaign_data['list_ids'] = ( ! empty( $newsletter['es_note_group'] ) && ! empty( $list_is_name_map[ $newsletter['es_note_group'] ] ) ) ? $list_is_name_map[ $newsletter['es_note_group'] ] : 0;
319
  $campaign_data['status'] = 1;
320
  $campaign_data['created_at'] = $newsletter['es_sent_starttime'];
321
+
322
  $campaign_data = wp_parse_args( $campaign_data, $this->get_column_defaults() );
323
+
324
  $formats = array();
325
  foreach ( $columns as $column => $format ) {
326
  $values[] = $campaign_data[ $column ];
327
  $formats[] = $format;
328
  }
329
+
330
  $place_holders[] = '( ' . implode( ', ', $formats ) . ' )';
331
  }
332
+
333
  ES_DB::do_insert( IG_CAMPAIGNS_TABLE, $fields, $place_holders, $values );
334
  }
335
  }
360
  break;
361
  }
362
  }
 
363
  }
364
  }
 
365
  }
366
 
367
  if ( ! empty( $data_to_update ) ) {
548
  /**
549
  * Update meta value
550
  *
551
+ * @param int $campaign_id
552
  * @param array $meta_data
553
  *
554
  * @return bool|false|int
574
 
575
  $update = $this->save_campaign( $campaign, $campaign_id );
576
 
 
577
  }
578
  }
579
  }
657
  $total_categories = count( $categories );
658
  if ( $total_categories > 0 ) {
659
  for ( $i = 0; $i < $total_categories; $i ++ ) {
660
+ if ( 0 === $i ) {
661
  $where .= ' and (';
662
  } else {
663
  $where .= ' or';
666
  $category_str = ES_Common::prepare_category_string( $categories[ $i ]->term_id );
667
 
668
  $where .= " categories LIKE '%" . $category_str . "%'";
669
+ if ( ( $total_categories - 1 ) === $i ) {
670
  $where .= " OR categories LIKE '%all%'";
671
  $where .= ") AND categories NOT LIKE '%none%'";
672
  }
673
  }
674
  } else {
675
+ // no categories fround for post
676
  return $campaigns;
677
  }
678
  } else {
690
  /**
691
  * Method to update campaign status
692
  *
693
+ * @param array $campaign_ids Campaign IDs.
694
  * @param integer $status New status.
695
  *
696
  * @return bool $updated Update status
715
 
716
  if ( ! empty( $id_str ) ) {
717
 
718
+ $updated = $wpbd->query( $wpbd->prepare( "UPDATE {$wpbd->prefix}ig_campaigns SET status = %d WHERE id IN({$id_str})", $status ) );
719
 
720
+ // Changing status of child campaigns along with its parent campaign id
721
+ $wpbd->query( $wpbd->prepare( "UPDATE {$wpbd->prefix}ig_campaigns SET status = %d WHERE parent_id IN({$id_str})", $status ) );
722
  }
723
 
724
  return $updated;
735
  public function duplicate_campaign( $id = null ) {
736
 
737
  if ( ! empty( $id ) ) {
738
+
739
+ $campaign = $this->get( $id );
740
  $campaign['status'] = IG_ES_CAMPAIGN_STATUS_IN_ACTIVE;
741
+ $campaign['name'] = __( 'Copy', 'email-subscribers' ) . ' - ' . $campaign['name'];
742
 
743
  if ( 'newsletter' === $campaign['type'] ) {
744
+ $campaign['subject'] = __( 'Copy', 'email-subscribers' ) . ' - ' . $campaign['subject'];
745
  }
746
+ $campaign_id = $campaign['id'];
747
  unset( $campaign['id'] );
748
  unset( $campaign['created_at'] );
749
 
750
  $duplicate_campaign_id = $this->save_campaign( $campaign );
751
+
752
  if ( 'sequence' === $campaign['type'] ) {
753
  $sequence_campaigns = $this->get_campaign_by_parent_id( $campaign_id );
754
 
764
 
765
  /**
766
  * Get all campaigns based on passed arguements
767
+ *
768
  * @param array $args Campaing arguements
769
+ *
770
  * @return array Array of campaigns
771
+ *
772
  * @since 4.6.11
773
  */
774
  public function get_all_campaigns( $args = array() ) {
779
  if ( ! empty( $args['include_types'] ) ) {
780
  $type_count = count( $args['include_types'] );
781
  $type_placeholders = array_fill( 0, $type_count, '%s' );
782
+ $where .= $wpbd->prepare( 'type IN( ' . implode( ',', $type_placeholders ) . ' )', $args['include_types'] );
783
  }
784
 
785
  if ( ! empty( $args['exclude_types'] ) ) {
786
  $type_count = count( $args['exclude_types'] );
787
  $type_placeholders = array_fill( 0, $type_count, '%s' );
788
+ $where .= $wpbd->prepare( 'type NOT IN( ' . implode( ',', $type_placeholders ) . ' )', $args['exclude_types'] );
789
  }
790
 
791
  if ( ! empty( $args['status'] ) ) {
792
  $status_count = count( $args['status'] );
793
  $status_placeholders = array_fill( 0, $status_count, '%d' );
794
+ $where .= $wpbd->prepare( ' AND status IN( ' . implode( ',', $status_placeholders ) . ' )', $args['status'] );
795
  }
796
+
797
  if ( ! empty( $args['campaigns_not_in'] ) ) {
798
  $ids_count = count( $args['campaigns_not_in'] );
799
  $ids_placeholders = array_fill( 0, $ids_count, '%d' );
800
+ $where .= $wpbd->prepare( ' AND id NOT IN( ' . implode( ',', $ids_placeholders ) . ' )', $args['campaigns_not_in'] );
801
  }
802
 
803
  return $this->get_by_conditions( $where );
805
 
806
  /**
807
  * Get selected lists ids in the campaign
808
+ *
809
  * @param int $campaign_id
810
+ *
811
  * @return array $list_ids
812
+ *
813
  * @since 4.7.6
814
  */
815
  public function get_list_ids( $campaign_id ) {
828
  if ( ! empty( $campaign['list_ids'] ) ) {
829
  $list_ids = explode( ',', $campaign['list_ids'] );
830
  }
831
+
832
  $campaign_meta = maybe_unserialize( $campaign['meta'] );
833
+ $conditions = isset( $campaign_meta['list_conditions'] ) ? $campaign_meta['list_conditions'] : array();
834
  if ( ! empty( $conditions ) ) {
835
  foreach ( $conditions as $i => $condition_group ) {
836
  if ( ! empty( $condition_group ) ) {
837
  foreach ( $condition_group as $j => $condition ) {
838
+ $condition_field = isset( $condition['field'] ) ? $condition['field'] : '';
839
  if ( '_lists__in' === $condition_field ) {
840
  if ( ! empty( $condition['value'] ) && is_array( $condition['value'] ) ) {
841
  $list_ids = array_merge( $list_ids, $condition['value'] );
lite/includes/db/class-es-db-contacts.php CHANGED
@@ -8,28 +8,25 @@ class ES_DB_Contacts extends ES_DB {
8
 
9
  /**
10
  * Table name
11
- *
12
  * @since 4.2.4
13
  * @var $table_name
14
- *
15
  */
16
  public $table_name;
17
 
18
  /**
19
  * Table DB version
20
- *
21
  * @since 4.2.4
22
  * @var $version
23
- *
24
  */
25
  public $version;
26
 
27
  /**
28
  * Table primary key column name
29
- *
30
  * @since 4.2.4
31
  * @var $primary_key
32
- *
33
  */
34
  public $primary_key;
35
 
@@ -65,8 +62,8 @@ class ES_DB_Contacts extends ES_DB {
65
  'last_name' => '%s',
66
  'email' => '%s',
67
  'source' => '%s',
68
- 'ip_address' => '%s',
69
- 'country_code' => '%s',
70
  'form_id' => '%d',
71
  'status' => '%s',
72
  'unsubscribed' => '%d',
@@ -95,8 +92,8 @@ class ES_DB_Contacts extends ES_DB {
95
  'last_name' => '',
96
  'email' => '',
97
  'source' => '',
98
- 'ip_address' => '',
99
- 'country_code' => '',
100
  'form_id' => 0,
101
  'status' => 'verified',
102
  'unsubscribed' => 0,
@@ -142,7 +139,7 @@ class ES_DB_Contacts extends ES_DB {
142
  $subscriber_email_name_map = array();
143
  if ( count( $emails ) > 0 ) {
144
 
145
- $emails_str = "'" . implode( "','", $emails ) . "'";
146
 
147
  $subscribers = $wpbd->get_results(
148
  "SELECT email, first_name, last_name FROM {$wpbd->prefix}ig_contacts WHERE email IN({$emails_str})",
@@ -156,7 +153,7 @@ class ES_DB_Contacts extends ES_DB {
156
  $subscriber_email_name_map[ $subscriber['email'] ] = array(
157
  'name' => $name,
158
  'first_name' => $subscriber['first_name'],
159
- 'last_name' => $subscriber['last_name']
160
  );
161
  }
162
  }
@@ -188,7 +185,7 @@ class ES_DB_Contacts extends ES_DB {
188
  'first_name' => $first_name,
189
  'last_name' => $last_name,
190
  'email' => $email,
191
- 'updated_at' => ig_get_current_date_time()
192
  );
193
 
194
  $this->update( $contact_id, $data_to_update );
@@ -252,7 +249,6 @@ class ES_DB_Contacts extends ES_DB {
252
  * @return array|object|null
253
  *
254
  * @since 4.2.4
255
- *
256
  */
257
  public function get_active_contacts_by_list_id( $list_id ) {
258
 
@@ -261,7 +257,7 @@ class ES_DB_Contacts extends ES_DB {
261
  }
262
 
263
  global $wpdb;
264
-
265
  // Check if we have got array of list ids.
266
  if ( is_array( $list_id ) ) {
267
  $list_ids_str = implode( ',', $list_id );
@@ -284,7 +280,6 @@ class ES_DB_Contacts extends ES_DB {
284
  * @return array|object|null
285
  *
286
  * @since 4.6.3
287
- *
288
  */
289
  public function get_active_contacts_by_list_and_mailing_queue_id( $list_id, $mailing_queue_id = 0 ) {
290
 
@@ -293,14 +288,14 @@ class ES_DB_Contacts extends ES_DB {
293
  }
294
 
295
  global $wpbd;
296
-
297
  // Check if we have got array of list ids.
298
  if ( is_array( $list_id ) ) {
299
  $ids_count = count( $list_id );
300
  $ids_placeholders = array_fill( 0, $ids_count, '%d' );
301
  $query_args = $list_id;
302
  $query_args[] = $mailing_queue_id;
303
- $where = $wpbd->prepare(
304
  "id IN (SELECT contact_id FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id IN( " . implode( ',', $ids_placeholders ) . " ) AND status IN ('subscribed', 'confirmed')) AND id NOT IN(SELECT contact_id FROM {$wpbd->prefix}ig_sending_queue WHERE mailing_queue_id = %d )",
305
  $query_args
306
  );
@@ -310,7 +305,7 @@ class ES_DB_Contacts extends ES_DB {
310
 
311
  return $this->get_by_conditions( $where );
312
  }
313
-
314
 
315
  /**
316
  * Get contacts by ids
@@ -424,11 +419,11 @@ class ES_DB_Contacts extends ES_DB {
424
 
425
  $ids_str = implode( ',', $ids );
426
 
427
- return $wpbd->query(
428
  $wpbd->prepare(
429
  "UPDATE {$wpbd->prefix}ig_contacts SET unsubscribed = %d WHERE id IN({$ids_str})",
430
  $unsubscribed
431
- )
432
  );
433
  }
434
 
@@ -462,7 +457,7 @@ class ES_DB_Contacts extends ES_DB {
462
  $list_ids_str = implode( ',', $list_id );
463
 
464
  $list_contact_count = $wpbd->get_var(
465
- $wpbd->prepare(
466
  "SELECT count(*) as count FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id IN ($list_ids_str) AND contact_id = %d",
467
  $contact_id
468
  )
@@ -488,7 +483,7 @@ class ES_DB_Contacts extends ES_DB {
488
  public function get_email_details_map() {
489
  global $wpdb;
490
 
491
- $contacts = $wpdb->get_results(
492
  "SELECT id, email, hash FROM {$wpdb->prefix}ig_contacts",
493
  ARRAY_A
494
  );
@@ -545,14 +540,15 @@ class ES_DB_Contacts extends ES_DB {
545
  if ( count( $emails ) > 0 ) {
546
  $ids_count = count( $emails );
547
  $ids_placeholders = array_fill( 0, $ids_count, '%s' );
548
- $results = $wpbd->get_results( $wpbd->prepare(
549
- "SELECT id, created_at FROM {$wpbd->prefix}ig_contacts WHERE email IN( " . implode( ',', $ids_placeholders ) . ' )',
550
- $emails
551
- ),
 
552
  ARRAY_A
553
  );
554
  } else {
555
- $results = $wpbd->get_results( "SELECT id , created_at FROM {$wpbd->prefix}ig_contacts" );
556
  }
557
 
558
  $map = array();
@@ -581,7 +577,7 @@ class ES_DB_Contacts extends ES_DB {
581
  if ( count( $emails ) > 0 ) {
582
  $email_count = count( $emails );
583
  $placeholders = array_fill( 0, $email_count, '%s' );
584
- $results = $wpbd->get_results(
585
  $wpbd->prepare(
586
  "SELECT id, email FROM {$wpbd->prefix}ig_contacts WHERE email IN( " . implode( ',', $placeholders ) . ' )',
587
  $emails
@@ -626,8 +622,8 @@ class ES_DB_Contacts extends ES_DB {
626
  */
627
  public function migrate_subscribers_from_older_version() {
628
  global $wpdb;
629
-
630
- //Get Total count of subscribers
631
  $total = $wpdb->get_var( "SELECT count(*) as total FROM {$wpdb->prefix}es_emaillist" );
632
 
633
  // If we have subscribers?
@@ -643,11 +639,11 @@ class ES_DB_Contacts extends ES_DB {
643
  $batch_size = IG_DEFAULT_BATCH_SIZE;
644
  $total_batches = ( $total > IG_DEFAULT_BATCH_SIZE ) ? ceil( $total / $batch_size ) : 1;
645
  $lists_contacts = array();
646
- //$exclude_status = array( 'Unsubscribed', 'Unconfirmed' );
647
  $j = 0;
648
  for ( $i = 0; $i < $total_batches; $i ++ ) {
649
  $batch_start = $i * $batch_size;
650
- $results = $wpdb->get_results(
651
  $wpdb->prepare(
652
  "SELECT * FROM {$wpdb->prefix}es_emaillist LIMIT %d, %d ",
653
  $batch_start,
@@ -665,7 +661,7 @@ class ES_DB_Contacts extends ES_DB {
665
 
666
  $names = array(
667
  'first_name' => '',
668
- 'last_name' => ''
669
  );
670
 
671
  if ( ! empty( $result['es_email_name'] ) ) {
@@ -689,19 +685,18 @@ class ES_DB_Contacts extends ES_DB {
689
  $emails[] = $email;
690
  }
691
 
692
- //Collect all contacts based on Lists
693
- //if ( ! in_array( $result['es_email_status'], $exclude_status ) ) {
694
  $lists_contacts[ $result['es_email_group'] ][ $j ]['email'] = $email;
695
  $lists_contacts[ $result['es_email_group'] ][ $j ]['status'] = $result['es_email_status'];
696
  $lists_contacts[ $result['es_email_group'] ][ $j ]['subscribed_at'] = $result['es_email_created'];
697
  $lists_contacts[ $result['es_email_group'] ][ $j ]['subscribed_ip'] = null;
698
  $j ++;
699
- //}
700
  }
701
 
702
  $this->bulk_insert( $contacts );
703
  }
704
-
705
  }
706
 
707
  // Do import Lists Contacts
@@ -758,7 +753,7 @@ class ES_DB_Contacts extends ES_DB {
758
  );
759
  } elseif ( 'unconfirmed' === $status ) {
760
  $query_result = $wpbd->query(
761
- $wpbd->prepare(
762
  "UPDATE {$wpbd->prefix}ig_lists_contacts SET status = %s, optin_type = %d, subscribed_at = NULL, unsubscribed_at = NULL WHERE contact_id IN( {$contact_ids} ) AND list_id IN( {$list_ids} )",
763
  array(
764
  $status,
@@ -775,7 +770,7 @@ class ES_DB_Contacts extends ES_DB {
775
  * Get total contacts by date
776
  *
777
  * @param string $status
778
- * @param int $days
779
  *
780
  * @return array
781
  *
@@ -812,7 +807,7 @@ class ES_DB_Contacts extends ES_DB {
812
  * Get total subscribed contacts by date
813
  *
814
  * @param string $status
815
- * @param int $days
816
  *
817
  * @return array
818
  *
@@ -899,7 +894,7 @@ class ES_DB_Contacts extends ES_DB {
899
 
900
  if ( 0 != $days ) {
901
  $days = esc_sql( $days );
902
- $where .= ' AND created_at > DATE_SUB(NOW(), INTERVAL %d DAY) AND created_at < DATE_SUB(NOW(), INTERVAL %d DAY) ';
903
  $args[] = $days * 2;
904
  $args[] = $days;
905
  }
@@ -926,13 +921,13 @@ class ES_DB_Contacts extends ES_DB {
926
  public function get_total_contacts_by_form_id( $form_id = '', $status = 0 ) {
927
 
928
  global $wpdb;
929
-
930
  $total_subscribers = '';
931
 
932
  if ( ! empty( $form_id ) ) {
933
  $total_subscribers = $wpdb->get_var(
934
  $wpdb->prepare(
935
- "SELECT count(distinct(id)) as total_active_subscribers FROM {$wpdb->prefix}ig_contacts where form_id = %d AND unsubscribed = %d" ,
936
  $form_id,
937
  $status
938
  )
@@ -950,13 +945,13 @@ class ES_DB_Contacts extends ES_DB {
950
  */
951
  public function migrate_ip_from_list_contacts_to_contacts_table() {
952
  global $wpdb;
953
-
954
- //Get Total count of subscribers
955
  $total = $wpdb->get_var( "SELECT count(*) as total FROM {$wpdb->prefix}ig_contacts" );
956
 
957
  // If we have subscribers?
958
  if ( $total > 0 ) {
959
-
960
  $wpdb->query(
961
  "UPDATE {$wpdb->prefix}ig_contacts AS contact_data
962
  LEFT JOIN {$wpdb->prefix}ig_lists_contacts AS list_data
@@ -981,15 +976,15 @@ class ES_DB_Contacts extends ES_DB {
981
  * @since 4.6.3
982
  */
983
  public function insert( $data, $type = '' ) {
984
- $source = array( 'admin','import' );
985
 
986
  if ( ! ES()->is_pro() ) {
987
  $data['ip_address'] = '';
988
  $data['country_code'] = '';
989
  } else {
990
-
991
  if ( empty( $data['ip_address'] ) && ! in_array( $data['source'], $source, true ) ) {
992
- $data = apply_filters( 'ig_es_get_subscriber_ip', $data, 'ip_address' );
993
  }
994
 
995
  if ( ! empty( $data['ip_address'] ) ) {
8
 
9
  /**
10
  * Table name
11
+ *
12
  * @since 4.2.4
13
  * @var $table_name
 
14
  */
15
  public $table_name;
16
 
17
  /**
18
  * Table DB version
19
+ *
20
  * @since 4.2.4
21
  * @var $version
 
22
  */
23
  public $version;
24
 
25
  /**
26
  * Table primary key column name
27
+ *
28
  * @since 4.2.4
29
  * @var $primary_key
 
30
  */
31
  public $primary_key;
32
 
62
  'last_name' => '%s',
63
  'email' => '%s',
64
  'source' => '%s',
65
+ 'ip_address' => '%s',
66
+ 'country_code' => '%s',
67
  'form_id' => '%d',
68
  'status' => '%s',
69
  'unsubscribed' => '%d',
92
  'last_name' => '',
93
  'email' => '',
94
  'source' => '',
95
+ 'ip_address' => '',
96
+ 'country_code' => '',
97
  'form_id' => 0,
98
  'status' => 'verified',
99
  'unsubscribed' => 0,
139
  $subscriber_email_name_map = array();
140
  if ( count( $emails ) > 0 ) {
141
 
142
+ $emails_str = "'" . implode( "','", $emails ) . "'";
143
 
144
  $subscribers = $wpbd->get_results(
145
  "SELECT email, first_name, last_name FROM {$wpbd->prefix}ig_contacts WHERE email IN({$emails_str})",
153
  $subscriber_email_name_map[ $subscriber['email'] ] = array(
154
  'name' => $name,
155
  'first_name' => $subscriber['first_name'],
156
+ 'last_name' => $subscriber['last_name'],
157
  );
158
  }
159
  }
185
  'first_name' => $first_name,
186
  'last_name' => $last_name,
187
  'email' => $email,
188
+ 'updated_at' => ig_get_current_date_time(),
189
  );
190
 
191
  $this->update( $contact_id, $data_to_update );
249
  * @return array|object|null
250
  *
251
  * @since 4.2.4
 
252
  */
253
  public function get_active_contacts_by_list_id( $list_id ) {
254
 
257
  }
258
 
259
  global $wpdb;
260
+
261
  // Check if we have got array of list ids.
262
  if ( is_array( $list_id ) ) {
263
  $list_ids_str = implode( ',', $list_id );
280
  * @return array|object|null
281
  *
282
  * @since 4.6.3
 
283
  */
284
  public function get_active_contacts_by_list_and_mailing_queue_id( $list_id, $mailing_queue_id = 0 ) {
285
 
288
  }
289
 
290
  global $wpbd;
291
+
292
  // Check if we have got array of list ids.
293
  if ( is_array( $list_id ) ) {
294
  $ids_count = count( $list_id );
295
  $ids_placeholders = array_fill( 0, $ids_count, '%d' );
296
  $query_args = $list_id;
297
  $query_args[] = $mailing_queue_id;
298
+ $where = $wpbd->prepare(
299
  "id IN (SELECT contact_id FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id IN( " . implode( ',', $ids_placeholders ) . " ) AND status IN ('subscribed', 'confirmed')) AND id NOT IN(SELECT contact_id FROM {$wpbd->prefix}ig_sending_queue WHERE mailing_queue_id = %d )",
300
  $query_args
301
  );
305
 
306
  return $this->get_by_conditions( $where );
307
  }
308
+
309
 
310
  /**
311
  * Get contacts by ids
419
 
420
  $ids_str = implode( ',', $ids );
421
 
422
+ return $wpbd->query(
423
  $wpbd->prepare(
424
  "UPDATE {$wpbd->prefix}ig_contacts SET unsubscribed = %d WHERE id IN({$ids_str})",
425
  $unsubscribed
426
+ )
427
  );
428
  }
429
 
457
  $list_ids_str = implode( ',', $list_id );
458
 
459
  $list_contact_count = $wpbd->get_var(
460
+ $wpbd->prepare(
461
  "SELECT count(*) as count FROM {$wpbd->prefix}ig_lists_contacts WHERE list_id IN ($list_ids_str) AND contact_id = %d",
462
  $contact_id
463
  )
483
  public function get_email_details_map() {
484
  global $wpdb;
485
 
486
+ $contacts = $wpdb->get_results(
487
  "SELECT id, email, hash FROM {$wpdb->prefix}ig_contacts",
488
  ARRAY_A
489
  );
540
  if ( count( $emails ) > 0 ) {
541
  $ids_count = count( $emails );
542
  $ids_placeholders = array_fill( 0, $ids_count, '%s' );
543
+ $results = $wpbd->get_results(
544
+ $wpbd->prepare(
545
+ "SELECT id, created_at FROM {$wpbd->prefix}ig_contacts WHERE email IN( " . implode( ',', $ids_placeholders ) . ' )',
546
+ $emails
547
+ ),
548
  ARRAY_A
549
  );
550
  } else {
551
+ $results = $wpbd->get_results( "SELECT id , created_at FROM {$wpbd->prefix}ig_contacts" );
552
  }
553
 
554
  $map = array();
577
  if ( count( $emails ) > 0 ) {
578
  $email_count = count( $emails );
579
  $placeholders = array_fill( 0, $email_count, '%s' );
580
+ $results = $wpbd->get_results(
581
  $wpbd->prepare(
582
  "SELECT id, email FROM {$wpbd->prefix}ig_contacts WHERE email IN( " . implode( ',', $placeholders ) . ' )',
583
  $emails
622
  */
623
  public function migrate_subscribers_from_older_version() {
624
  global $wpdb;
625
+
626
+ // Get Total count of subscribers
627
  $total = $wpdb->get_var( "SELECT count(*) as total FROM {$wpdb->prefix}es_emaillist" );
628
 
629
  // If we have subscribers?
639
  $batch_size = IG_DEFAULT_BATCH_SIZE;
640
  $total_batches = ( $total > IG_DEFAULT_BATCH_SIZE ) ? ceil( $total / $batch_size ) : 1;
641
  $lists_contacts = array();
642
+ // $exclude_status = array( 'Unsubscribed', 'Unconfirmed' );
643
  $j = 0;
644
  for ( $i = 0; $i < $total_batches; $i ++ ) {
645
  $batch_start = $i * $batch_size;
646
+ $results = $wpdb->get_results(
647
  $wpdb->prepare(
648
  "SELECT * FROM {$wpdb->prefix}es_emaillist LIMIT %d, %d ",
649
  $batch_start,
661
 
662
  $names = array(
663
  'first_name' => '',
664
+ 'last_name' => '',
665
  );
666
 
667
  if ( ! empty( $result['es_email_name'] ) ) {
685
  $emails[] = $email;
686
  }
687
 
688
+ // Collect all contacts based on Lists
689
+ // if ( ! in_array( $result['es_email_status'], $exclude_status ) ) {
690
  $lists_contacts[ $result['es_email_group'] ][ $j ]['email'] = $email;
691
  $lists_contacts[ $result['es_email_group'] ][ $j ]['status'] = $result['es_email_status'];
692
  $lists_contacts[ $result['es_email_group'] ][ $j ]['subscribed_at'] = $result['es_email_created'];
693
  $lists_contacts[ $result['es_email_group'] ][ $j ]['subscribed_ip'] = null;
694
  $j ++;
695
+ // }
696
  }
697
 
698
  $this->bulk_insert( $contacts );
699
  }
 
700
  }
701
 
702
  // Do import Lists Contacts
753
  );
754
  } elseif ( 'unconfirmed' === $status ) {
755
  $query_result = $wpbd->query(
756
+ $wpbd->prepare(
757
  "UPDATE {$wpbd->prefix}ig_lists_contacts SET status = %s, optin_type = %d, subscribed_at = NULL, unsubscribed_at = NULL WHERE contact_id IN( {$contact_ids} ) AND list_id IN( {$list_ids} )",
758
  array(
759
  $status,
770
  * Get total contacts by date
771
  *
772
  * @param string $status
773
+ * @param int $days
774
  *
775
  * @return array
776
  *
807
  * Get total subscribed contacts by date
808
  *
809
  * @param string $status
810
+ * @param int $days
811
  *
812
  * @return array
813
  *
894
 
895
  if ( 0 != $days ) {
896
  $days = esc_sql( $days );
897
+ $where .= ' AND created_at > DATE_SUB(NOW(), INTERVAL %d DAY) AND created_at < DATE_SUB(NOW(), INTERVAL %d DAY) ';
898
  $args[] = $days * 2;
899
  $args[] = $days;
900
  }
921
  public function get_total_contacts_by_form_id( $form_id = '', $status = 0 ) {
922
 
923
  global $wpdb;
924
+
925
  $total_subscribers = '';
926
 
927
  if ( ! empty( $form_id ) ) {
928
  $total_subscribers = $wpdb->get_var(
929
  $wpdb->prepare(
930
+ "SELECT count(distinct(id)) as total_active_subscribers FROM {$wpdb->prefix}ig_contacts where form_id = %d AND unsubscribed = %d",
931
  $form_id,
932
  $status
933
  )
945
  */
946
  public function migrate_ip_from_list_contacts_to_contacts_table() {
947
  global $wpdb;
948
+
949
+ // Get Total count of subscribers
950
  $total = $wpdb->get_var( "SELECT count(*) as total FROM {$wpdb->prefix}ig_contacts" );
951
 
952
  // If we have subscribers?
953
  if ( $total > 0 ) {
954
+
955
  $wpdb->query(
956
  "UPDATE {$wpdb->prefix}ig_contacts AS contact_data
957
  LEFT JOIN {$wpdb->prefix}ig_lists_contacts AS list_data
976
  * @since 4.6.3
977
  */
978
  public function insert( $data, $type = '' ) {
979
+ $source = array( 'admin', 'import' );
980
 
981
  if ( ! ES()->is_pro() ) {
982
  $data['ip_address'] = '';
983
  $data['country_code'] = '';
984
  } else {
985
+
986
  if ( empty( $data['ip_address'] ) && ! in_array( $data['source'], $source, true ) ) {
987
+ $data = apply_filters( 'ig_es_get_subscriber_ip', $data, 'ip_address' );
988
  }
989
 
990
  if ( ! empty( $data['ip_address'] ) ) {
lite/includes/db/class-es-db-forms.php CHANGED
@@ -6,31 +6,28 @@ if ( ! defined( 'ABSPATH' ) ) {
6
  }
7
 
8
  class ES_DB_Forms extends ES_DB {
9
-
10
  /**
11
  * Table name
12
- *
13
  * @since 4.2.2
14
  * @var string
15
- *
16
  */
17
  public $table_name;
18
 
19
  /**
20
  * Table DB version
21
- *
22
  * @since 4.2.2
23
  * @var string
24
- *
25
  */
26
  public $version;
27
 
28
  /**
29
  * Table primary key column name
30
- *
31
  * @since 4.2.2
32
  * @var string
33
- *
34
  */
35
  public $primary_key;
36
 
@@ -68,7 +65,7 @@ class ES_DB_Forms extends ES_DB {
68
  'created_at' => '%s',
69
  'updated_at' => '%s',
70
  'deleted_at' => '%s',
71
- 'af_id' => '%d'
72
  );
73
  }
74
 
@@ -86,7 +83,7 @@ class ES_DB_Forms extends ES_DB {
86
  'created_at' => ig_get_current_date_time(),
87
  'updated_at' => null,
88
  'deleted_at' => null,
89
- 'af_id' => 0
90
  );
91
  }
92
 
@@ -228,62 +225,62 @@ class ES_DB_Forms extends ES_DB {
228
 
229
  $body = array(
230
  array(
231
- 'type' => 'text',
232
- 'name' => 'Name',
233
- 'id' => 'name',
234
- 'params' => array(
235
  'label' => 'Name',
236
  'show' => ( 'YES' === $es_af_name ) ? true : false,
237
- 'required' => ( 'YES' === $es_af_name_mand ) ? true : false
238
  ),
239
 
240
- 'position' => 1
241
  ),
242
 
243
  array(
244
- 'type' => 'text',
245
- 'name' => 'Email',
246
- 'id' => 'email',
247
- 'params' => array(
248
  'label' => 'Email',
249
  'show' => ( 'YES' === $es_af_email ) ? true : false,
250
- 'required' => ( 'YES' === $es_af_email_mand ) ? true : false
251
  ),
252
 
253
- 'position' => 2
254
  ),
255
 
256
  array(
257
- 'type' => 'checkbox',
258
- 'name' => 'Lists',
259
- 'id' => 'lists',
260
- 'params' => array(
261
  'label' => 'Lists',
262
  'show' => ( 'YES' === $es_af_group ) ? true : false,
263
  'required' => ( 'YES' === $es_af_group_mand ) ? true : false,
264
- 'values' => $list_ids
265
  ),
266
 
267
- 'position' => 3
268
  ),
269
 
270
  array(
271
- 'type' => 'submit',
272
- 'name' => 'submit',
273
- 'id' => 'submit',
274
- 'params' => array(
275
  'label' => 'Subscribe',
276
- 'show' => true
277
  ),
278
 
279
- 'position' => 4
280
  ),
281
 
282
  );
283
 
284
  $settings = array(
285
  'lists' => $list_ids,
286
- 'desc' => $es_af_desc
287
  );
288
 
289
  $data[ $key ]['name'] = $es_af_title;
6
  }
7
 
8
  class ES_DB_Forms extends ES_DB {
9
+
10
  /**
11
  * Table name
12
+ *
13
  * @since 4.2.2
14
  * @var string
 
15
  */
16
  public $table_name;
17
 
18
  /**
19
  * Table DB version
20
+ *
21
  * @since 4.2.2
22
  * @var string
 
23
  */
24
  public $version;
25
 
26
  /**
27
  * Table primary key column name
28
+ *
29
  * @since 4.2.2
30
  * @var string
 
31
  */
32
  public $primary_key;
33
 
65
  'created_at' => '%s',
66
  'updated_at' => '%s',
67
  'deleted_at' => '%s',
68
+ 'af_id' => '%d',
69
  );
70
  }
71
 
83
  'created_at' => ig_get_current_date_time(),
84
  'updated_at' => null,
85
  'deleted_at' => null,
86
+ 'af_id' => 0,
87
  );
88
  }
89
 
225
 
226
  $body = array(
227
  array(
228
+ 'type' => 'text',
229
+ 'name' => 'Name',
230
+ 'id' => 'name',
231
+ 'params' => array(
232
  'label' => 'Name',
233
  'show' => ( 'YES' === $es_af_name ) ? true : false,
234
+ 'required' => ( 'YES' === $es_af_name_mand ) ? true : false,
235
  ),
236
 
237
+ 'position' => 1,
238
  ),
239
 
240
  array(
241
+ 'type' => 'text',
242
+ 'name' => 'Email',
243
+ 'id' => 'email',
244
+ 'params' => array(
245
  'label' => 'Email',
246
  'show' => ( 'YES' === $es_af_email ) ? true : false,
247
+ 'required' => ( 'YES' === $es_af_email_mand ) ? true : false,
248
  ),
249
 
250
+ 'position' => 2,
251
  ),
252
 
253
  array(
254
+ 'type' => 'checkbox',
255
+ 'name' => 'Lists',
256
+ 'id' => 'lists',
257
+ 'params' => array(
258
  'label' => 'Lists',
259
  'show' => ( 'YES' === $es_af_group ) ? true : false,
260
  'required' => ( 'YES' === $es_af_group_mand ) ? true : false,
261
+ 'values' => $list_ids,
262
  ),
263
 
264
+ 'position' => 3,
265
  ),
266
 
267
  array(
268
+ 'type' => 'submit',
269
+ 'name' => 'submit',
270
+ 'id' => 'submit',
271
+ 'params' => array(
272
  'label' => 'Subscribe',
273
+ 'show' => true,
274
  ),
275
 
276
+ 'position' => 4,
277
  ),
278
 
279
  );
280
 
281
  $settings = array(
282
  'lists' => $list_ids,
283
+ 'desc' => $es_af_desc,
284
  );
285
 
286
  $data[ $key ]['name'] = $es_af_title;
lite/includes/db/class-es-db-links.php CHANGED
@@ -18,7 +18,6 @@ if ( ! class_exists( 'ES_DB_Links' ) ) {
18
  *
19
  * @since 4.2.4
20
  * @var string
21
- *
22
  */
23
  public $table_name;
24
  /**
@@ -26,7 +25,6 @@ if ( ! class_exists( 'ES_DB_Links' ) ) {
26
  *
27
  * @since 4.2.4
28
  * @var string
29
- *
30
  */
31
  public $version;
32
  /**
@@ -34,7 +32,6 @@ if ( ! class_exists( 'ES_DB_Links' ) ) {
34
  *
35
  * @since 4.2.4
36
  * @var string
37
- *
38
  */
39
  public $primary_key;
40
 
@@ -131,9 +128,9 @@ if ( ! class_exists( 'ES_DB_Links' ) ) {
131
  * Check whether link exists in campaign
132
  *
133
  * @param $link
134
- * @param int $campaign_id
135
- * @param int $message_id
136
- * @param int $index
137
  *
138
  * @return string|null
139
  *
18
  *
19
  * @since 4.2.4
20
  * @var string
 
21
  */
22
  public $table_name;
23
  /**
25
  *
26
  * @since 4.2.4
27
  * @var string
 
28
  */
29
  public $version;
30
  /**
32
  *
33
  * @since 4.2.4
34
  * @var string
 
35
  */
36
  public $primary_key;
37
 
128
  * Check whether link exists in campaign
129
  *
130
  * @param $link
131
+ * @param int $campaign_id
132
+ * @param int $message_id
133
+ * @param int $index
134
  *
135
  * @return string|null
136
  *
lite/includes/db/class-es-db-lists-contacts.php CHANGED
@@ -5,10 +5,10 @@ if ( ! defined( 'ABSPATH' ) ) {
5
  }
6
 
7
  class ES_DB_Lists_Contacts extends ES_DB {
8
-
9
  /**
10
  * Table name
11
- *
12
  * @since 4.3.5
13
  *
14
  * @var $table_name
@@ -17,7 +17,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
17
 
18
  /**
19
  * Table DB version
20
- *
21
  * @since 4.3.5
22
  *
23
  * @var $version
@@ -26,7 +26,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
26
 
27
  /**
28
  * Table primary key column name
29
- *
30
  * @since 4.3.5
31
  *
32
  * @var $primary_key
@@ -107,7 +107,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
107
 
108
  if ( is_array( $list_ids ) && count( $list_ids ) > 0 ) {
109
 
110
- $contact_data = apply_filters( 'ig_es_get_subscriber_ip', $contact_data, 'subscribed_ip' );
111
 
112
  // Remove entry if it's already there in a list
113
  $contact_id = ! empty( $contact_data['contact_id'] ) ? $contact_data['contact_id'] : 0;
@@ -127,7 +127,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
127
  /**
128
  * Prepare contact_data
129
  *
130
- * @param array $contact_ids
131
  * @param $list_id
132
  *
133
  * @return array|bool
@@ -156,14 +156,13 @@ class ES_DB_Lists_Contacts extends ES_DB {
156
  'list_id' => $list_id,
157
  'status' => 'subscribed',
158
  'optin_type' => $optin_type,
159
- 'subscribed_at' => ig_get_current_date_time()
160
  );
161
 
162
  foreach ( $contact_ids as $contact_id ) {
163
  $data['contact_id'] = $contact_id;
164
  $contact_data[] = $data;
165
  }
166
-
167
  }
168
 
169
  return $contact_data;
@@ -173,7 +172,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
173
  * Add contacts to list
174
  *
175
  * @param array $contact_ids
176
- * @param int $list_id
177
  *
178
  * @return bool
179
  *
@@ -206,7 +205,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
206
  * Move multiple contacts to specific list
207
  *
208
  * @param array $contact_ids
209
- * @param int $list_id
210
  *
211
  * @return bool
212
  *
@@ -234,7 +233,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
234
 
235
  /**
236
  * Get list ids by contact id
237
- *
238
  * @param $id
239
  * @param string $status
240
  *
@@ -261,7 +260,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
261
 
262
  /**
263
  * Get mapping of contact status with list
264
- *
265
  * @param int $contact_id
266
  *
267
  * @return array
@@ -285,7 +284,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
285
  /**
286
  * Update lists of contact
287
  *
288
- * @param int $contact_id
289
  * @param array $list_ids
290
  *
291
  * @return bool
@@ -380,7 +379,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
380
  /**
381
  * Remove all contacts from specific list
382
  *
383
- * @param int $list_id
384
  * @param array $contact_ids
385
  *
386
  * @return bool
@@ -394,7 +393,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
394
  /**
395
  * Import contacts into lists
396
  *
397
- * @param int $list_id
398
  * @param array $contacts
399
  *
400
  * @return bool
@@ -424,8 +423,8 @@ class ES_DB_Lists_Contacts extends ES_DB {
424
  }
425
 
426
  $contacts[ $key ]['contact_id'] = $email_id_map[ $contact['email'] ];
427
- $status = 'subscribed';
428
- $optin_type = IG_SINGLE_OPTIN;
429
  if ( 'Single Opt In' === $contact['status'] ) {
430
  $optin_type = IG_SINGLE_OPTIN;
431
  } elseif ( 'Confirmed' === $contact['status'] ) {
@@ -454,14 +453,14 @@ class ES_DB_Lists_Contacts extends ES_DB {
454
  /**
455
  * Add contacts into lists_contacts table
456
  *
457
- * @param array $list_ids
458
- * @param array $contacts
459
  * @param string $status
460
- * @param int $optin_type
461
- * @param null $subscribed_at
462
- * @param null $subscribed_ip
463
- * @param null $unsubscribed_at
464
- * @param null $unsubscribed_ip
465
  *
466
  * @return bool
467
  *
@@ -476,7 +475,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
476
  if ( ! is_array( $list_ids ) ) {
477
  $list_ids = array( absint( $list_ids ) );
478
  }
479
-
480
  $key = 0;
481
  foreach ( $contacts as $contact_id => $created_at ) {
482
  foreach ( $list_ids as $list_id ) {
@@ -489,7 +488,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
489
  $values[ $key ]['subscribed_ip'] = $subscribed_ip;
490
  $values[ $key ]['unsubscribed_at'] = $unsubscribed_at;
491
  $values[ $key ]['unsubscribed_ip'] = $unsubscribed_ip;
492
-
493
  $key ++;
494
  }
495
  }
@@ -503,7 +502,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
503
  /**
504
  * Get total contacts based on list & status
505
  *
506
- * @param int $list_id
507
  * @param string $status
508
  *
509
  * @return string|null
@@ -614,25 +613,25 @@ class ES_DB_Lists_Contacts extends ES_DB {
614
  $ids = array_map( 'absint', $ids );
615
  $status = esc_sql( $status );
616
 
617
- $ids_str = implode( ',', $ids );
618
-
619
  $current_date = ig_get_current_date_time();
620
-
621
  $query = '';
622
  if ( 'subscribed' === $status ) {
623
- if ( ! empty ( $list_ids ) ) {
624
-
625
  $list_ids_str = implode( ',', $list_ids );
626
- $result = $wpbd->query(
627
- $wpbd->prepare(
628
- "UPDATE {$wpbd->prefix}ig_lists_contacts SET status = %s, subscribed_at = %s WHERE contact_id IN( {$ids_str} ) AND list_id IN( {$list_ids_str} )",
629
- array(
630
- $status,
631
- $current_date,
632
  )
633
  )
634
  );
635
- } else {
636
  $result = $wpbd->query(
637
  $wpbd->prepare(
638
  "UPDATE {$wpbd->prefix}ig_lists_contacts SET status = %s, subscribed_at = %s WHERE contact_id IN( {$ids_str} )",
@@ -653,10 +652,10 @@ class ES_DB_Lists_Contacts extends ES_DB {
653
  $current_date,
654
  )
655
  )
656
- );
657
  } elseif ( 'unconfirmed' === $status ) {
658
  return $wpbd->query(
659
- $wpbd->prepare(
660
  "UPDATE {$wpbd->prefix}ig_lists_contacts SET status = %s, optin_type = %d, subscribed_at = NULL, unsubscribed_at = NULL WHERE contact_id IN( {$ids_str} )",
661
  array(
662
  $status,
@@ -690,7 +689,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
690
 
691
  $ids = array_map( 'absint', $ids );
692
  $ids_str = implode( ',', $ids );
693
-
694
  $where = $wpbd->prepare( "contact_id IN($ids_str) && status != %s", $status );
695
 
696
  if ( $this->count( $where ) ) {
@@ -733,7 +732,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
733
  /**
734
  * Get all confirmed contacts
735
  *
736
- * @param int $days
737
  * @param bool $distinct
738
  *
739
  * @return array|object|null
@@ -747,7 +746,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
747
  /**
748
  * Get all unconfirmed contacts
749
  *
750
- * @param int $days
751
  * @param bool $distinct
752
  *
753
  * @return array|object|null
@@ -761,7 +760,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
761
  /**
762
  * Get all contacts count
763
  *
764
- * @param int $days
765
  * @param bool $distinct
766
  *
767
  * @return array|object|null
@@ -776,10 +775,10 @@ class ES_DB_Lists_Contacts extends ES_DB {
776
  * Get all contacts based on status, list, days, count
777
  *
778
  * @param string $status
779
- * @param int $list_id
780
- * @param int $days
781
- * @param bool $count_only
782
- * @param bool $distinct
783
  *
784
  * @return array|object|string|null
785
  *
@@ -826,8 +825,8 @@ class ES_DB_Lists_Contacts extends ES_DB {
826
  $ids_count = count( $list_id );
827
  $ids_placeholders = array_fill( 0, $ids_count, '%d' );
828
  $ids_query = ' list_id IN( ' . implode( ',', $ids_placeholders ) . ' )';
829
- $where[] = $ids_query;
830
- $args = array_merge( $args, $list_id );
831
  } else {
832
  $list_id = absint( $list_id );
833
  if ( ! empty( $list_id ) ) {
@@ -857,7 +856,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
857
  $where = implode( ' AND ', $where );
858
  $where = $wpbd->prepare( $where, $args );
859
  }
860
-
861
  if ( $count_only ) {
862
  return $this->get_total_contacts( $where, $distinct );
863
  } else {
@@ -869,7 +868,7 @@ class ES_DB_Lists_Contacts extends ES_DB {
869
  * Get contacts from list based on status
870
  *
871
  * @param string $status
872
- * @param int $list_id
873
  *
874
  * @return array|object|null
875
  *
5
  }
6
 
7
  class ES_DB_Lists_Contacts extends ES_DB {
8
+
9
  /**
10
  * Table name
11
+ *
12
  * @since 4.3.5
13
  *
14
  * @var $table_name
17
 
18
  /**
19
  * Table DB version
20
+ *
21
  * @since 4.3.5
22
  *
23
  * @var $version
26
 
27
  /**
28
  * Table primary key column name
29
+ *
30
  * @since 4.3.5
31
  *
32
  * @var $primary_key
107
 
108
  if ( is_array( $list_ids ) && count( $list_ids ) > 0 ) {
109
 
110
+ $contact_data = apply_filters( 'ig_es_get_subscriber_ip', $contact_data, 'subscribed_ip' );
111
 
112
  // Remove entry if it's already there in a list
113
  $contact_id = ! empty( $contact_data['contact_id'] ) ? $contact_data['contact_id'] : 0;
127
  /**
128
  * Prepare contact_data
129
  *
130
+ * @param array $contact_ids
131
  * @param $list_id
132
  *
133
  * @return array|bool
156
  'list_id' => $list_id,
157
  'status' => 'subscribed',
158
  'optin_type' => $optin_type,
159
+ 'subscribed_at' => ig_get_current_date_time(),
160
  );
161
 
162
  foreach ( $contact_ids as $contact_id ) {
163
  $data['contact_id'] = $contact_id;
164
  $contact_data[] = $data;
165
  }
 
166
  }
167
 
168
  return $contact_data;
172
  * Add contacts to list
173
  *
174
  * @param array $contact_ids
175
+ * @param int $list_id
176
  *
177
  * @return bool
178
  *
205
  * Move multiple contacts to specific list
206
  *
207
  * @param array $contact_ids
208
+ * @param int $list_id
209
  *
210
  * @return bool
211
  *
233
 
234
  /**
235
  * Get list ids by contact id
236
+ *
237
  * @param $id
238
  * @param string $status
239
  *
260
 
261
  /**
262
  * Get mapping of contact status with list
263
+ *
264
  * @param int $contact_id
265
  *
266
  * @return array
284
  /**
285
  * Update lists of contact
286
  *
287
+ * @param int $contact_id
288
  * @param array $list_ids
289
  *
290
  * @return bool
379
  /**
380
  * Remove all contacts from specific list
381
  *
382
+ * @param int $list_id
383
  * @param array $contact_ids
384
  *
385
  * @return bool
393
  /**
394
  * Import contacts into lists
395
  *
396
+ * @param int $list_id
397
  * @param array $contacts
398
  *
399
  * @return bool
423
  }
424
 
425
  $contacts[ $key ]['contact_id'] = $email_id_map[ $contact['email'] ];
426
+ $status = 'subscribed';
427
+ $optin_type = IG_SINGLE_OPTIN;
428
  if ( 'Single Opt In' === $contact['status'] ) {
429
  $optin_type = IG_SINGLE_OPTIN;
430
  } elseif ( 'Confirmed' === $contact['status'] ) {
453
  /**
454
  * Add contacts into lists_contacts table
455
  *
456
+ * @param array $list_ids
457
+ * @param array $contacts
458
  * @param string $status
459
+ * @param int $optin_type
460
+ * @param null $subscribed_at
461
+ * @param null $subscribed_ip
462
+ * @param null $unsubscribed_at
463
+ * @param null $unsubscribed_ip
464
  *
465
  * @return bool
466
  *
475
  if ( ! is_array( $list_ids ) ) {
476
  $list_ids = array( absint( $list_ids ) );
477
  }
478
+
479
  $key = 0;
480
  foreach ( $contacts as $contact_id => $created_at ) {
481
  foreach ( $list_ids as $list_id ) {
488
  $values[ $key ]['subscribed_ip'] = $subscribed_ip;
489
  $values[ $key ]['unsubscribed_at'] = $unsubscribed_at;
490
  $values[ $key ]['unsubscribed_ip'] = $unsubscribed_ip;
491
+
492
  $key ++;
493
  }
494
  }
502
  /**
503
  * Get total contacts based on list & status
504
  *
505
+ * @param int $list_id
506
  * @param string $status
507
  *
508
  * @return string|null
613
  $ids = array_map( 'absint', $ids );
614
  $status = esc_sql( $status );
615
 
616
+ $ids_str = implode( ',', $ids );
617
+
618
  $current_date = ig_get_current_date_time();
619
+
620
  $query = '';
621
  if ( 'subscribed' === $status ) {
622
+ if ( ! empty( $list_ids ) ) {
623
+
624
  $list_ids_str = implode( ',', $list_ids );
625
+ $result = $wpbd->query(
626
+ $wpbd->prepare(
627
+ "UPDATE {$wpbd->prefix}ig_lists_contacts SET status = %s, subscribed_at = %s WHERE contact_id IN( {$ids_str} ) AND list_id IN( {$list_ids_str} )",
628
+ array(
629
+ $status,
630
+ $current_date,
631
  )
632
  )
633
  );
634
+ } else {
635
  $result = $wpbd->query(
636
  $wpbd->prepare(
637
  "UPDATE {$wpbd->prefix}ig_lists_contacts SET status = %s, subscribed_at = %s WHERE contact_id IN( {$ids_str} )",
652
  $current_date,
653
  )
654
  )
655
+ );
656
  } elseif ( 'unconfirmed' === $status ) {
657
  return $wpbd->query(
658
+ $wpbd->prepare(
659
  "UPDATE {$wpbd->prefix}ig_lists_contacts SET status = %s, optin_type = %d, subscribed_at = NULL, unsubscribed_at = NULL WHERE contact_id IN( {$ids_str} )",
660
  array(
661
  $status,
689
 
690
  $ids = array_map( 'absint', $ids );
691
  $ids_str = implode( ',', $ids );
692
+
693
  $where = $wpbd->prepare( "contact_id IN($ids_str) && status != %s", $status );
694
 
695
  if ( $this->count( $where ) ) {
732
  /**
733
  * Get all confirmed contacts
734
  *
735
+ * @param int $days
736
  * @param bool $distinct
737
  *
738
  * @return array|object|null
746
  /**
747
  * Get all unconfirmed contacts
748
  *
749
+ * @param int $days
750
  * @param bool $distinct
751
  *
752
  * @return array|object|null
760
  /**
761
  * Get all contacts count
762
  *
763
+ * @param int $days
764
  * @param bool $distinct
765
  *
766
  * @return array|object|null
775
  * Get all contacts based on status, list, days, count
776
  *
777
  * @param string $status
778
+ * @param int $list_id
779
+ * @param int $days
780
+ * @param bool $count_only
781
+ * @param bool $distinct
782
  *
783
  * @return array|object|string|null
784
  *
825
  $ids_count = count( $list_id );
826
  $ids_placeholders = array_fill( 0, $ids_count, '%d' );
827
  $ids_query = ' list_id IN( ' . implode( ',', $ids_placeholders ) . ' )';
828
+ $where[] = $ids_query;
829
+ $args = array_merge( $args, $list_id );
830
  } else {
831
  $list_id = absint( $list_id );
832
  if ( ! empty( $list_id ) ) {
856
  $where = implode( ' AND ', $where );
857
  $where = $wpbd->prepare( $where, $args );
858
  }
859
+
860
  if ( $count_only ) {
861
  return $this->get_total_contacts( $where, $distinct );
862
  } else {
868
  * Get contacts from list based on status
869
  *
870
  * @param string $status
871
+ * @param int $list_id
872
  *
873
  * @return array|object|null
874
  *
lite/includes/db/class-es-db-lists.php CHANGED
@@ -5,31 +5,28 @@ if ( ! defined( 'ABSPATH' ) ) {
5
  }
6
 
7
  class ES_DB_Lists extends ES_DB {
8
-
9
  /**
10
  * Table name
11
- *
12
  * @since 4.0.0
13
  * @var $table_name
14
- *
15
  */
16
  public $table_name;
17
-
18
  /**
19
  * Table DB version
20
- *
21
  * @since 4.0.0
22
  * @var $version
23
- *
24
  */
25
  public $version;
26
-
27
  /**
28
  * Table primary key column name
29
- *
30
  * @since 4.0.0
31
  * @var $primary_key
32
- *
33
  */
34
  public $primary_key;
35
 
@@ -49,7 +46,6 @@ class ES_DB_Lists extends ES_DB {
49
 
50
  $this->version = '1.0';
51
 
52
-
53
  }
54
 
55
  /**
@@ -102,7 +98,7 @@ class ES_DB_Lists extends ES_DB {
102
  * Get list id name map
103
  *
104
  * @param string $list_id
105
- * @param bool $flip
106
  *
107
  * @return array|mixed|string
108
  *
@@ -155,7 +151,8 @@ class ES_DB_Lists extends ES_DB {
155
 
156
  return $list;
157
 
158
- /* TODO: Keep for sometime. Remove it after complete verification/ testing
 
159
  global $wpdb;
160
 
161
  $lists = array();
@@ -204,9 +201,9 @@ class ES_DB_Lists extends ES_DB {
204
  * @since 4.6.12
205
  */
206
  public function get_lists_by_id( $list_ids = array() ) {
207
-
208
  global $wpdb;
209
-
210
  if ( empty( $list_ids ) ) {
211
  return array();
212
  }
@@ -237,11 +234,11 @@ class ES_DB_Lists extends ES_DB {
237
  public function get_all_lists_name_by_contact( $id ) {
238
  global $wpdb;
239
 
240
- $res = $wpdb->get_col(
241
  $wpdb->prepare(
242
  "SELECT `name` FROM {$wpdb->prefix}ig_lists WHERE id IN ( SELECT list_id FROM {$wpdb->prefix}ig_lists_contacts WHERE contact_id = %d )",
243
  $id
244
- )
245
  );
246
 
247
  return $res;
@@ -294,7 +291,7 @@ class ES_DB_Lists extends ES_DB {
294
  * @return int
295
  *
296
  * @since 4.0.0
297
- *
298
  * @modified 4.4.3 Added $slug parameter.
299
  */
300
  public function add_list( $list = '', $slug = '' ) {
@@ -302,15 +299,15 @@ class ES_DB_Lists extends ES_DB {
302
  if ( empty( $list ) || ! is_scalar( $list ) ) {
303
  return 0;
304
  }
305
-
306
  $lower_list = strtolower( $list );
307
-
308
  $is_list_exists = $this->is_list_exists( $lower_list );
309
-
310
  if ( $is_list_exists ) {
311
  return 0;
312
  }
313
-
314
  $data = array(
315
  'slug' => ! empty( $slug ) ? $slug : sanitize_title( $list ),
316
  'name' => $list,
@@ -349,7 +346,7 @@ class ES_DB_Lists extends ES_DB {
349
  /**
350
  * Update List
351
  *
352
- * @param int $row_id
353
  * @param array $data
354
  *
355
  * @return bool|void
@@ -364,7 +361,7 @@ class ES_DB_Lists extends ES_DB {
364
 
365
  $data = array(
366
  'name' => $name,
367
- 'updated_at' => ig_get_current_date_time()
368
  );
369
 
370
  return $this->update( $row_id, $data );
@@ -415,9 +412,9 @@ class ES_DB_Lists extends ES_DB {
415
 
416
  /**
417
  * Get list names by ids
418
- *
419
  * @param array $list_ids List ids
420
- *
421
  * @return array $list_names List name
422
  */
423
  public function get_list_name_by_ids( $list_ids = array() ) {
@@ -447,7 +444,7 @@ class ES_DB_Lists extends ES_DB {
447
  if ( is_array( $ids ) && count( $ids ) > 0 ) {
448
 
449
  foreach ( $ids as $id ) {
450
- $this->delete( absint($id) );
451
 
452
  /**
453
  * Take necessary cleanup steps using this hook
@@ -499,7 +496,7 @@ class ES_DB_Lists extends ES_DB {
499
  public function get_lists_by_hash( $list_hashes = array() ) {
500
 
501
  global $wpbd;
502
-
503
  if ( empty( $list_hashes ) ) {
504
  return array();
505
  }
@@ -510,7 +507,7 @@ class ES_DB_Lists extends ES_DB {
510
 
511
  $hash_count = count( $list_hashes );
512
  $hash_placeholders = array_fill( 0, $hash_count, '%s' );
513
- $where = $wpbd->prepare(
514
  'hash IN( ' . implode( ',', $hash_placeholders ) . ')',
515
  $list_hashes
516
  );
5
  }
6
 
7
  class ES_DB_Lists extends ES_DB {
8
+
9
  /**
10
  * Table name
11
+ *
12
  * @since 4.0.0
13
  * @var $table_name
 
14
  */
15
  public $table_name;
16
+
17
  /**
18
  * Table DB version
19
+ *
20
  * @since 4.0.0
21
  * @var $version
 
22
  */
23
  public $version;
24
+
25
  /**
26
  * Table primary key column name
27
+ *
28
  * @since 4.0.0
29
  * @var $primary_key
 
30
  */
31
  public $primary_key;
32
 
46
 
47
  $this->version = '1.0';
48
 
 
49
  }
50
 
51
  /**
98
  * Get list id name map
99
  *
100
  * @param string $list_id
101
+ * @param bool $flip
102
  *
103
  * @return array|mixed|string
104
  *
151
 
152
  return $list;
153
 
154
+ /*
155
+ TODO: Keep for sometime. Remove it after complete verification/ testing
156
  global $wpdb;
157
 
158
  $lists = array();
201
  * @since 4.6.12
202
  */
203
  public function get_lists_by_id( $list_ids = array() ) {
204
+
205
  global $wpdb;
206
+
207
  if ( empty( $list_ids ) ) {
208
  return array();
209
  }
234
  public function get_all_lists_name_by_contact( $id ) {
235
  global $wpdb;
236
 
237
+ $res = $wpdb->get_col(
238
  $wpdb->prepare(
239
  "SELECT `name` FROM {$wpdb->prefix}ig_lists WHERE id IN ( SELECT list_id FROM {$wpdb->prefix}ig_lists_contacts WHERE contact_id = %d )",
240
  $id
241
+ )
242
  );
243
 
244
  return $res;
291
  * @return int
292
  *
293
  * @since 4.0.0
294
+ *
295
  * @modified 4.4.3 Added $slug parameter.
296
  */
297
  public function add_list( $list = '', $slug = '' ) {
299
  if ( empty( $list ) || ! is_scalar( $list ) ) {
300
  return 0;
301
  }
302
+
303
  $lower_list = strtolower( $list );
304
+
305
  $is_list_exists = $this->is_list_exists( $lower_list );
306
+
307
  if ( $is_list_exists ) {
308
  return 0;
309
  }
310
+
311
  $data = array(
312
  'slug' => ! empty( $slug ) ? $slug : sanitize_title( $list ),
313
  'name' => $list,
346
  /**
347
  * Update List
348
  *
349
+ * @param int $row_id
350
  * @param array $data
351
  *
352
  * @return bool|void
361
 
362
  $data = array(
363
  'name' => $name,
364
+ 'updated_at' => ig_get_current_date_time(),
365
  );
366
 
367
  return $this->update( $row_id, $data );
412
 
413
  /**
414
  * Get list names by ids
415
+ *
416
  * @param array $list_ids List ids
417
+ *
418
  * @return array $list_names List name
419
  */
420
  public function get_list_name_by_ids( $list_ids = array() ) {
444
  if ( is_array( $ids ) && count( $ids ) > 0 ) {
445
 
446
  foreach ( $ids as $id ) {
447
+ $this->delete( absint( $id ) );
448
 
449
  /**
450
  * Take necessary cleanup steps using this hook
496
  public function get_lists_by_hash( $list_hashes = array() ) {
497
 
498
  global $wpbd;
499
+
500
  if ( empty( $list_hashes ) ) {
501
  return array();
502
  }
507
 
508
  $hash_count = count( $list_hashes );
509
  $hash_placeholders = array_fill( 0, $hash_count, '%s' );
510
+ $where = $wpbd->prepare(
511
  'hash IN( ' . implode( ',', $hash_placeholders ) . ')',
512
  $list_hashes
513
  );
lite/includes/db/class-es-db-mailing-queue.php CHANGED
@@ -41,7 +41,7 @@ class ES_DB_Mailing_Queue {
41
  'finish_at' => '%s',
42
  'created_at' => '%s',
43
  'updated_at' => '%s',
44
- 'meta' => '%s'
45
  );
46
  }
47
 
@@ -57,7 +57,7 @@ class ES_DB_Mailing_Queue {
57
  'finish_at' => null,
58
  'created_at' => ig_get_current_date_time(),
59
  'updated_at' => null,
60
- 'meta' => null
61
  );
62
  }
63
 
@@ -71,7 +71,7 @@ class ES_DB_Mailing_Queue {
71
  )
72
  );
73
 
74
- //TODO :: update start date
75
 
76
  return $hash;
77
 
@@ -86,7 +86,7 @@ class ES_DB_Mailing_Queue {
86
 
87
  $results = array();
88
  if ( ! empty( $campaign_hash ) ) {
89
- $results = $wpdb->get_results(
90
  $wpdb->prepare(
91
  "SELECT * FROM {$wpdb->prefix}ig_mailing_queue WHERE hash = %s",
92
  array( $campaign_hash )
@@ -95,7 +95,7 @@ class ES_DB_Mailing_Queue {
95
  );
96
  } else {
97
  $current_time = ig_get_current_date_time();
98
- $results = $wpdb->get_results(
99
  $wpdb->prepare(
100
  "SELECT * FROM {$wpdb->prefix}ig_mailing_queue WHERE status IN ('Sending', 'In Queue') AND start_at <= %s ORDER BY start_at, id LIMIT 0, 1",
101
  $current_time
@@ -106,7 +106,7 @@ class ES_DB_Mailing_Queue {
106
 
107
  if ( count( $results ) > 0 ) {
108
  $notification = array_shift( $results );
109
-
110
  }
111
 
112
  return $notification;
@@ -115,9 +115,9 @@ class ES_DB_Mailing_Queue {
115
 
116
  /**
117
  * Sync mailing queue content with campaign content
118
- *
119
  * @param array $notification
120
- *
121
  * @since 4.7.3
122
  */
123
  public static function sync_content( $notification = array() ) {
@@ -130,24 +130,31 @@ class ES_DB_Mailing_Queue {
130
  $filter = 'ig_es_refresh_' . $meta['type'] . '_content';
131
  $post_id = ! empty( $meta['post_id'] ) ? $meta['post_id'] : 0;
132
  $content = array();
133
- $content = apply_filters( $filter, $content, array( 'campaign_id' => $notification['campaign_id'], 'post_id' => $post_id ) );
134
-
 
 
 
 
 
 
 
135
  // Update mailing queue with updated content data.
136
  if ( ! empty( $content ) ) {
137
  global $wpdb;
138
-
139
  $notification['subject'] = ! empty( $content['subject'] ) ? $content['subject'] : $notification['subject'];
140
  $notification['body'] = ! empty( $content['body'] ) ? $content['body'] : $notification['body'];
141
 
142
- $wpdb->query(
143
- $wpdb->prepare(
144
- "UPDATE {$wpdb->prefix}ig_mailing_queue SET subject = %s, body = %s WHERE hash = %s",
145
  array(
146
  $notification['subject'],
147
  $notification['body'],
148
  $notification['hash'],
149
  )
150
- )
151
  );
152
  }
153
  }
@@ -160,11 +167,11 @@ class ES_DB_Mailing_Queue {
160
  public static function update_sent_status( $hash = '', $status = 'In Queue' ) {
161
 
162
  global $wpdb;
163
-
164
  // If status is sent then add finish_at time as well.
165
  if ( 'Sent' === $status ) {
166
  $current_date_time = ig_get_current_date_time();
167
- $return_id = $wpdb->query(
168
  $wpdb->prepare(
169
  "UPDATE {$wpdb->prefix}ig_mailing_queue SET status = %s, finish_at = %s WHERE hash = %s",
170
  $status,
@@ -174,7 +181,7 @@ class ES_DB_Mailing_Queue {
174
  );
175
  } elseif ( 'Sending' === $status ) {
176
  $current_date_time = ig_get_current_date_time();
177
- $return_id = $wpdb->query(
178
  $wpdb->prepare(
179
  "UPDATE {$wpdb->prefix}ig_mailing_queue SET status = %s, start_at = %s WHERE hash = %s",
180
  $status,
@@ -199,7 +206,7 @@ class ES_DB_Mailing_Queue {
199
  public static function get_sent_email_count( $notification_hash ) {
200
  global $wpdb;
201
  $email_count = $wpdb->get_col(
202
- $wpdb->prepare(
203
  "SELECT count FROM {$wpdb->prefix}ig_mailing_queue WHERE hash = %s ",
204
  array( $notification_hash )
205
  )
@@ -213,12 +220,12 @@ class ES_DB_Mailing_Queue {
213
  global $wpbd;
214
 
215
  $notification = array();
216
- $query = $wpbd->prepare(
217
  "SELECT * FROM {$wpbd->prefix}ig_mailing_queue WHERE hash = %s",
218
  $notification_hash
219
  );
220
 
221
- $cache_key = ES_Cache::generate_key( $query );
222
  $exists_in_cache = ES_Cache::is_exists( $cache_key, 'query' );
223
  if ( ! $exists_in_cache ) {
224
  $results = $wpbd->get_results(
@@ -229,7 +236,7 @@ class ES_DB_Mailing_Queue {
229
  } else {
230
  $results = ES_Cache::get( $cache_key, 'query' );
231
  }
232
-
233
  if ( count( $results ) > 0 ) {
234
  $notification = array_shift( $results );
235
  }
@@ -242,8 +249,8 @@ class ES_DB_Mailing_Queue {
242
 
243
  $notification = array();
244
  $query = $wpbd->prepare( "SELECT * FROM {$wpbd->prefix}ig_mailing_queue WHERE campaign_id = %d", $campaign_id );
245
-
246
- $cache_key = ES_Cache::generate_key( $query );
247
  $exists_in_cache = ES_Cache::is_exists( $cache_key, 'query' );
248
  if ( ! $exists_in_cache ) {
249
  $results = $wpbd->get_results(
@@ -267,7 +274,7 @@ class ES_DB_Mailing_Queue {
267
 
268
  if ( ! empty( $per_page ) && ! empty( $page_number ) ) {
269
  $start_limit = ( $page_number - 1 ) * $per_page;
270
- $result = $wpdb->get_results(
271
  $wpdb->prepare(
272
  "SELECT * FROM {$wpdb->prefix}ig_mailing_queue ORDER BY created_at DESC LIMIT %d, %d",
273
  $start_limit,
@@ -276,7 +283,7 @@ class ES_DB_Mailing_Queue {
276
  ARRAY_A
277
  );
278
  } else {
279
- $result = $wpdb->get_results(
280
  $wpdb->prepare(
281
  "SELECT * FROM {$wpdb->prefix}ig_mailing_queue ORDER BY created_at DESC "
282
  ),
@@ -369,7 +376,7 @@ class ES_DB_Mailing_Queue {
369
  global $wpdb;
370
 
371
  $query = 'SELECT id, start_at, hash FROM ' . IG_MAILING_QUEUE_TABLE;
372
- $results = $wpdb->get_results(
373
  $wpdb->prepare(
374
  "SELECT id, start_at, hash FROM {$wpdb->prefix}ig_mailing_queue WHERE %d",
375
  1
@@ -391,7 +398,7 @@ class ES_DB_Mailing_Queue {
391
  global $wpdb;
392
 
393
  $report = array();
394
- $results = $wpdb->get_results(
395
  $wpdb->prepare(
396
  "SELECT * FROM {$wpdb->prefix}ig_mailing_queue WHERE id = %s",
397
  $mailing_queue_id
@@ -408,7 +415,7 @@ class ES_DB_Mailing_Queue {
408
 
409
  /**
410
  * Get recent campaigns data
411
- *
412
  * @param int $count
413
  *
414
  * @return array|object|null
@@ -422,7 +429,7 @@ class ES_DB_Mailing_Queue {
422
  $count = 5;
423
  }
424
 
425
- return $wpdb->get_results(
426
  $wpdb->prepare(
427
  "SELECT id, hash, campaign_id, subject, start_at, status, finish_at FROM {$wpdb->prefix}ig_mailing_queue order by created_at DESC LIMIT 0, %d",
428
  $count
@@ -510,20 +517,20 @@ class ES_DB_Mailing_Queue {
510
 
511
  /**
512
  * Method to update subscribers count in mailing queue table.
513
- *
514
  * @param string $hash Mailing queue hash.
515
- * @param int $count Subscribers count.
516
- *
517
  * @since 4.6.3
518
- */
519
  public static function update_subscribers_count( $hash = '', $count = 0 ) {
520
 
521
  global $wpdb;
522
-
523
  if ( empty( $hash ) ) {
524
  return;
525
  }
526
-
527
  $wpdb->query(
528
  $wpdb->prepare(
529
  "UPDATE {$wpdb->prefix}ig_mailing_queue SET count = %d WHERE hash = %s",
@@ -535,20 +542,20 @@ class ES_DB_Mailing_Queue {
535
 
536
  /**
537
  * Decrease subscribers count by given amount.
538
- *
539
  * @param int $mailing_queue_id Mailing queue id.
540
  * @param int $decrease_by Subscribers count.
541
- *
542
  * @since 4.7.6
543
- */
544
  public static function decrease_subscribers_count( $mailing_queue_id, $decrease_by = 0 ) {
545
 
546
  global $wpdb;
547
-
548
  if ( empty( $mailing_queue_id ) || empty( $decrease_by ) ) {
549
  return;
550
  }
551
-
552
  $wpdb->query(
553
  $wpdb->prepare(
554
  "UPDATE {$wpdb->prefix}ig_mailing_queue SET count = count - %d WHERE id = %d",
41
  'finish_at' => '%s',
42
  'created_at' => '%s',
43
  'updated_at' => '%s',
44
+ 'meta' => '%s',
45
  );
46
  }
47
 
57
  'finish_at' => null,
58
  'created_at' => ig_get_current_date_time(),
59
  'updated_at' => null,
60
+ 'meta' => null,
61
  );
62
  }
63
 
71
  )
72
  );
73
 
74
+ // TODO :: update start date
75
 
76
  return $hash;
77
 
86
 
87
  $results = array();
88
  if ( ! empty( $campaign_hash ) ) {
89
+ $results = $wpdb->get_results(
90
  $wpdb->prepare(
91
  "SELECT * FROM {$wpdb->prefix}ig_mailing_queue WHERE hash = %s",
92
  array( $campaign_hash )
95
  );
96
  } else {
97
  $current_time = ig_get_current_date_time();
98
+ $results = $wpdb->get_results(
99
  $wpdb->prepare(
100
  "SELECT * FROM {$wpdb->prefix}ig_mailing_queue WHERE status IN ('Sending', 'In Queue') AND start_at <= %s ORDER BY start_at, id LIMIT 0, 1",
101
  $current_time
106
 
107
  if ( count( $results ) > 0 ) {
108
  $notification = array_shift( $results );
109
+
110
  }
111
 
112
  return $notification;
115
 
116
  /**
117
  * Sync mailing queue content with campaign content
118
+ *
119
  * @param array $notification
120
+ *
121
  * @since 4.7.3
122
  */
123
  public static function sync_content( $notification = array() ) {
130
  $filter = 'ig_es_refresh_' . $meta['type'] . '_content';
131
  $post_id = ! empty( $meta['post_id'] ) ? $meta['post_id'] : 0;
132
  $content = array();
133
+ $content = apply_filters(
134
+ $filter,
135
+ $content,
136
+ array(
137
+ 'campaign_id' => $notification['campaign_id'],
138
+ 'post_id' => $post_id,
139
+ )
140
+ );
141
+
142
  // Update mailing queue with updated content data.
143
  if ( ! empty( $content ) ) {
144
  global $wpdb;
145
+
146
  $notification['subject'] = ! empty( $content['subject'] ) ? $content['subject'] : $notification['subject'];
147
  $notification['body'] = ! empty( $content['body'] ) ? $content['body'] : $notification['body'];
148
 
149
+ $wpdb->query(
150
+ $wpdb->prepare(
151
+ "UPDATE {$wpdb->prefix}ig_mailing_queue SET subject = %s, body = %s WHERE hash = %s",
152
  array(
153
  $notification['subject'],
154
  $notification['body'],
155
  $notification['hash'],
156
  )
157
+ )
158
  );
159
  }
160
  }
167
  public static function update_sent_status( $hash = '', $status = 'In Queue' ) {
168
 
169
  global $wpdb;
170
+
171
  // If status is sent then add finish_at time as well.
172
  if ( 'Sent' === $status ) {
173
  $current_date_time = ig_get_current_date_time();
174
+ $return_id = $wpdb->query(
175
  $wpdb->prepare(
176
  "UPDATE {$wpdb->prefix}ig_mailing_queue SET status = %s, finish_at = %s WHERE hash = %s",
177
  $status,
181
  );
182
  } elseif ( 'Sending' === $status ) {
183
  $current_date_time = ig_get_current_date_time();
184
+ $return_id = $wpdb->query(
185
  $wpdb->prepare(
186
  "UPDATE {$wpdb->prefix}ig_mailing_queue SET status = %s, start_at = %s WHERE hash = %s",
187
  $status,
206
  public static function get_sent_email_count( $notification_hash ) {
207
  global $wpdb;
208
  $email_count = $wpdb->get_col(
209
+ $wpdb->prepare(
210
  "SELECT count FROM {$wpdb->prefix}ig_mailing_queue WHERE hash = %s ",
211
  array( $notification_hash )
212
  )
220
  global $wpbd;
221
 
222
  $notification = array();
223
+ $query = $wpbd->prepare(
224
  "SELECT * FROM {$wpbd->prefix}ig_mailing_queue WHERE hash = %s",
225
  $notification_hash
226
  );
227
 
228
+ $cache_key = ES_Cache::generate_key( $query );
229
  $exists_in_cache = ES_Cache::is_exists( $cache_key, 'query' );
230
  if ( ! $exists_in_cache ) {
231
  $results = $wpbd->get_results(
236
  } else {
237
  $results = ES_Cache::get( $cache_key, 'query' );
238
  }
239
+
240
  if ( count( $results ) > 0 ) {
241
  $notification = array_shift( $results );
242
  }
249
 
250
  $notification = array();
251
  $query = $wpbd->prepare( "SELECT * FROM {$wpbd->prefix}ig_mailing_queue WHERE campaign_id = %d", $campaign_id );
252
+
253
+ $cache_key = ES_Cache::generate_key( $query );
254
  $exists_in_cache = ES_Cache::is_exists( $cache_key, 'query' );
255
  if ( ! $exists_in_cache ) {
256
  $results = $wpbd->get_results(
274
 
275
  if ( ! empty( $per_page ) && ! empty( $page_number ) ) {
276
  $start_limit = ( $page_number - 1 ) * $per_page;
277
+ $result = $wpdb->get_results(
278
  $wpdb->prepare(
279
  "SELECT * FROM {$wpdb->prefix}ig_mailing_queue ORDER BY created_at DESC LIMIT %d, %d",
280
  $start_limit,
283
  ARRAY_A
284
  );
285
  } else {
286
+ $result = $wpdb->get_results(
287
  $wpdb->prepare(
288
  "SELECT * FROM {$wpdb->prefix}ig_mailing_queue ORDER BY created_at DESC "
289
  ),
376
  global $wpdb;
377
 
378
  $query = 'SELECT id, start_at, hash FROM ' . IG_MAILING_QUEUE_TABLE;
379
+ $results = $wpdb->get_results(
380
  $wpdb->prepare(
381
  "SELECT id, start_at, hash FROM {$wpdb->prefix}ig_mailing_queue WHERE %d",
382
  1
398
  global $wpdb;
399
 
400
  $report = array();
401
+ $results = $wpdb->get_results(
402
  $wpdb->prepare(
403
  "SELECT * FROM {$wpdb->prefix}ig_mailing_queue WHERE id = %s",
404
  $mailing_queue_id
415
 
416
  /**
417
  * Get recent campaigns data
418
+ *
419
  * @param int $count
420
  *
421
  * @return array|object|null
429
  $count = 5;
430
  }
431
 
432
+ return $wpdb->get_results(
433
  $wpdb->prepare(
434
  "SELECT id, hash, campaign_id, subject, start_at, status, finish_at FROM {$wpdb->prefix}ig_mailing_queue order by created_at DESC LIMIT 0, %d",
435
  $count
517
 
518
  /**
519
  * Method to update subscribers count in mailing queue table.
520
+ *
521
  * @param string $hash Mailing queue hash.
522
+ * @param int $count Subscribers count.
523
+ *
524
  * @since 4.6.3
525
+ */
526
  public static function update_subscribers_count( $hash = '', $count = 0 ) {
527
 
528
  global $wpdb;
529
+
530
  if ( empty( $hash ) ) {
531
  return;
532
  }
533
+
534
  $wpdb->query(
535
  $wpdb->prepare(
536
  "UPDATE {$wpdb->prefix}ig_mailing_queue SET count = %d WHERE hash = %s",
542
 
543
  /**
544
  * Decrease subscribers count by given amount.
545
+ *
546
  * @param int $mailing_queue_id Mailing queue id.
547
  * @param int $decrease_by Subscribers count.
548
+ *
549
  * @since 4.7.6
550
+ */
551
  public static function decrease_subscribers_count( $mailing_queue_id, $decrease_by = 0 ) {
552
 
553
  global $wpdb;
554
+
555
  if ( empty( $mailing_queue_id ) || empty( $decrease_by ) ) {
556
  return;
557
  }
558
+
559
  $wpdb->query(
560
  $wpdb->prepare(
561
  "UPDATE {$wpdb->prefix}ig_mailing_queue SET count = count - %d WHERE id = %d",
lite/includes/db/class-es-db-notifications.php CHANGED
@@ -26,7 +26,7 @@ class ES_DB_Notifications {
26
  */
27
  public static function migrate_post_notification_es_template_type() {
28
  global $wpdb;
29
-
30
  $update = $wpdb->query(
31
  $wpdb->prepare(
32
  "UPDATE {$wpdb->prefix}postmeta SET meta_value = %s WHERE meta_key = %s AND meta_value = %s",
@@ -48,7 +48,7 @@ class ES_DB_Notifications {
48
  global $wpdb;
49
 
50
  $update = $wpdb->query(
51
- $wpdb->prepare(
52
  "UPDATE {$wpdb->prefix}postmeta SET meta_value = %s WHERE meta_key = %s AND meta_value = %s",
53
  array( 'newsletter', 'es_template_type', 'Newsletter' )
54
  )
26
  */
27
  public static function migrate_post_notification_es_template_type() {
28
  global $wpdb;
29
+
30
  $update = $wpdb->query(
31
  $wpdb->prepare(
32
  "UPDATE {$wpdb->prefix}postmeta SET meta_value = %s WHERE meta_key = %s AND meta_value = %s",
48
  global $wpdb;
49
 
50
  $update = $wpdb->query(
51
+ $wpdb->prepare(
52
  "UPDATE {$wpdb->prefix}postmeta SET meta_value = %s WHERE meta_key = %s AND meta_value = %s",
53
  array( 'newsletter', 'es_template_type', 'Newsletter' )
54
  )
lite/includes/db/class-es-db-queue.php CHANGED
@@ -12,28 +12,25 @@ if ( ! defined( 'ABSPATH' ) ) {
12
  class ES_DB_Queue extends ES_DB {
13
  /**
14
  * Table name
15
- *
16
  * @since 4.2.1
17
  * @var $table_name
18
- *
19
  */
20
  public $table_name;
21
 
22
  /**
23
  * Table DB version
24
- *
25
  * @since 4.2.1
26
  * @var $version
27
- *
28
  */
29
  public $version;
30
 
31
  /**
32
  * Table primary key column name
33
- *
34
  * @since 4.2.1
35
  * @var $primary_key
36
- *
37
  */
38
  public $primary_key;
39
 
@@ -62,7 +59,7 @@ class ES_DB_Queue extends ES_DB {
62
  *
63
  * @since 4.2.1
64
  */
65
- public function delete_from_queue( $campaign_id, $contact_id) {
66
  global $wpdb;
67
 
68
  return $wpdb->query(
12
  class ES_DB_Queue extends ES_DB {
13
  /**
14
  * Table name
15
+ *
16
  * @since 4.2.1
17
  * @var $table_name
 
18
  */
19
  public $table_name;
20
 
21
  /**
22
  * Table DB version
23
+ *
24
  * @since 4.2.1
25
  * @var $version
 
26
  */
27
  public $version;
28
 
29
  /**
30
  * Table primary key column name
31
+ *
32
  * @since 4.2.1
33
  * @var $primary_key
 
34
  */
35
  public $primary_key;
36
 
59
  *
60
  * @since 4.2.1
61
  */
62
+ public function delete_from_queue( $campaign_id, $contact_id ) {
63
  global $wpdb;
64
 
65
  return $wpdb->query(
lite/includes/db/class-es-db-sending-queue.php CHANGED
@@ -54,12 +54,12 @@ class ES_DB_Sending_Queue {
54
  global $wpdb;
55
 
56
  $subscribers = $wpdb->get_results(
57
- $wpdb->prepare(
58
  "SELECT * FROM {$wpdb->prefix}ig_sending_queue WHERE status = %s AND mailing_queue_hash = %s ORDER BY id LIMIT 0, %d",
59
  array(
60
  'In Queue',
61
  $guid,
62
- $limit
63
  )
64
  ),
65
  ARRAY_A
@@ -69,19 +69,19 @@ class ES_DB_Sending_Queue {
69
  }
70
 
71
  /**
72
- * Get contact queued emails
73
- *
74
  * @param int $contact_id
75
- *
76
  * @return array $queued_emails
77
- *
78
  * @since 4.7.6
79
  */
80
  public static function get_queued_emails( $contact_id ) {
81
  global $wpdb;
82
 
83
  $queued_emails = $wpdb->get_results(
84
- $wpdb->prepare(
85
  "SELECT * FROM {$wpdb->prefix}ig_sending_queue WHERE contact_id = %d AND status = %s",
86
  $contact_id,
87
  'In Queue'
@@ -110,7 +110,7 @@ class ES_DB_Sending_Queue {
110
  if ( ! empty( $id_str ) ) {
111
  if ( 'Sent' === $status ) {
112
  $current_time = ig_get_current_date_time();
113
- $updated = $wpbd->query(
114
  $wpbd->prepare(
115
  "UPDATE {$wpbd->prefix}ig_sending_queue SET status = %s, sent_at = %s WHERE mailing_queue_id = %d AND contact_id IN($id_str)",
116
  $status,
@@ -156,12 +156,12 @@ class ES_DB_Sending_Queue {
156
 
157
  global $wpdb;
158
 
159
- $result = $wpdb->get_var(
160
  $wpdb->prepare(
161
  "SELECT COUNT(*) AS count FROM {$wpdb->prefix}ig_sending_queue WHERE status = %s",
162
  array( 'In Queue' )
163
  )
164
- );
165
 
166
  return $result;
167
 
@@ -207,8 +207,8 @@ class ES_DB_Sending_Queue {
207
  if ( $result === $wpdb->prefix . 'es_deliverreport' ) {
208
  $emails = $wpdb->get_results(
209
  $wpdb->prepare(
210
- "SELECT * FROM {$wpdb->prefix}es_deliverreport WHERE es_deliver_sentguid = %s",
211
- array( $notification_hash )
212
  ),
213
  ARRAY_A
214
  );
@@ -287,40 +287,40 @@ class ES_DB_Sending_Queue {
287
 
288
  /**
289
  * Method to insert sending queue data from contact table.
290
- *
291
- * @param int $mailing_queue_id Mailing queue ID.
292
- * @param string $mailing_queue_hash Mailing Hash.
293
- * @param int $campaign_id Campaign ID.
294
  * @param array|string $list_ids List IDs seperated by commas if string i.e. '1,2,3' or array( 1, 2, 3 ) if array.
295
- *
296
  * @return bool $is_inserted Is contacts inserted into sending_queue table.
297
- *
298
  * @since 4.6.4
299
  */
300
  public static function do_insert_from_contacts_table( $mailing_queue_id = 0, $mailing_queue_hash = '', $campaign_id = 0, $list_ids = array() ) {
301
 
302
  global $wpbd;
303
-
304
  $is_inserted = false;
305
-
306
  if ( empty( $mailing_queue_id ) || empty( $mailing_queue_hash ) || empty( $campaign_id ) ) {
307
  return $is_inserted;
308
  }
309
-
310
  $column_defaults = self::get_column_defaults();
311
-
312
  $queue_status = 'In Queue';
313
- $queue_links = isset( $column_defaults['links'] ) ? $column_defaults['links'] : '';
314
- $queue_opened = isset( $column_defaults['opened'] ) ? $column_defaults['opened'] : 0;
315
- $queue_sent_at = isset( $column_defaults['sent_at'] ) ? $column_defaults['sent_at']: null;
316
  $queue_opened_at = isset( $column_defaults['opened_at'] ) ? $column_defaults['opened_at'] : null;
317
-
318
  $campaign = ES()->campaigns_db->get( $campaign_id );
319
- $args = array(
320
  'select' => array( 'subscribers.id' ),
321
  'lists' => $list_ids,
322
  'return_sql' => true, // This flag will return the required sql query
323
- 'orderby' => array( 'id'),
324
  );
325
  if ( ! empty( $campaign ) && ! empty( $campaign['meta'] ) ) {
326
  $campaign_meta = maybe_unserialize( $campaign['meta'] );
@@ -341,7 +341,7 @@ class ES_DB_Sending_Queue {
341
  $queue_sent_at,
342
  $queue_opened_at,
343
  );
344
-
345
  $total_contacts_added = $wpbd->query(
346
  $wpbd->prepare(
347
  "INSERT INTO `{$wpbd->prefix}ig_sending_queue`
@@ -376,21 +376,21 @@ class ES_DB_Sending_Queue {
376
  $query_args
377
  )
378
  );
379
-
380
  // Check if contacts added.
381
  if ( ! empty( $total_contacts_added ) ) {
382
  $is_inserted = true;
383
  ES_DB_Mailing_Queue::update_subscribers_count( $mailing_queue_hash, $total_contacts_added );
384
  } else {
385
-
386
  // If some how above sql query fails then queue emails using old approach.
387
  // i.e. Preparing data for insert query in PHP and then doing insert.
388
-
389
  // Converto to an array if already not an array.
390
  if ( ! is_array( $list_ids ) ) {
391
  $list_ids = explode( ',', $list_ids );
392
  }
393
-
394
  $subscribers = ES()->contacts_db->get_active_contacts_by_list_id( $list_ids );
395
  $subscribers_count = count( $subscribers );
396
  if ( $subscribers_count > 0 ) {
@@ -401,13 +401,13 @@ class ES_DB_Sending_Queue {
401
  $delivery_data['subscribers'] = $subscribers;
402
  $delivery_data['campaign_id'] = $campaign_id;
403
  $delivery_data['mailing_queue_id'] = $mailing_queue_id;
404
- $is_inserted = self::do_batch_insert( $delivery_data );
405
  if ( $is_inserted ) {
406
  ES_DB_Mailing_Queue::update_subscribers_count( $mailing_queue_hash, $subscribers_count );
407
  }
408
  }
409
  }
410
-
411
  return $is_inserted;
412
  }
413
 
@@ -429,7 +429,7 @@ class ES_DB_Sending_Queue {
429
  }
430
 
431
  /*
432
- * Commenting for now as we might need this function in the future.
433
  public static function migrate_reports_data() {
434
  global $wpdb;
435
 
@@ -603,7 +603,7 @@ class ES_DB_Sending_Queue {
603
  }
604
  }
605
  */
606
-
607
  public static function delete_records_from_delivereport( $ids ) {
608
  global $wpbd;
609
 
@@ -616,12 +616,12 @@ class ES_DB_Sending_Queue {
616
 
617
  public static function delete_sending_queue_by_mailing_id( $mailing_queue_ids ) {
618
  global $wpbd;
619
-
620
  $mailing_queue_ids = esc_sql( $mailing_queue_ids );
621
  $mailing_queue_ids = implode( ',', array_map( 'absint', $mailing_queue_ids ) );
622
 
623
  $wpbd->query(
624
- "DELETE FROM {$wpbd->prefix}ig_sending_queue WHERE mailing_queue_id IN ($mailing_queue_ids)"
625
  );
626
  }
627
 
@@ -655,7 +655,7 @@ class ES_DB_Sending_Queue {
655
  if ( '' != $hash ) {
656
  $result = $wpdb->get_var(
657
  $wpdb->prepare(
658
- "SELECT COUNT(*) AS count FROM {$wpdb->prefix}ig_sending_queue WHERE mailing_queue_hash = %s",
659
  array( $hash )
660
  )
661
  );
@@ -706,11 +706,11 @@ class ES_DB_Sending_Queue {
706
  return $wpbd->get_var( $wpbd->prepare( $query, $args ) );
707
  }
708
 
709
-
710
  /**
711
  * Get Email => ID map based on Sending Queue table
712
- *
713
- * @param int $campaign_id
714
  * @param array $emails
715
  *
716
  * @return array
@@ -729,11 +729,11 @@ class ES_DB_Sending_Queue {
729
 
730
  $emails_str = "'" . implode( "','", $emails ) . "'";
731
 
732
- $results = $wpbd->get_results(
733
  $wpbd->prepare(
734
- "SELECT contact_id, email FROM {$wpbd->prefix}ig_sending_queue WHERE campaign_id = %d AND email IN($emails_str)",
735
  $campaign_id
736
- ),
737
  ARRAY_A
738
  );
739
 
@@ -774,14 +774,14 @@ class ES_DB_Sending_Queue {
774
 
775
  /**
776
  * Delete contacts from the sending queue
777
- *
778
  * @param array $contact_ids
779
- * @param int $message_id
780
- *
781
- * @since 4.7.6
782
  */
783
  public static function delete_contacts( $contact_ids, $message_id ) {
784
-
785
  global $wpbd;
786
 
787
  if ( ! empty( $contact_ids ) && ! empty( $message_id ) ) {
54
  global $wpdb;
55
 
56
  $subscribers = $wpdb->get_results(
57
+ $wpdb->prepare(
58
  "SELECT * FROM {$wpdb->prefix}ig_sending_queue WHERE status = %s AND mailing_queue_hash = %s ORDER BY id LIMIT 0, %d",
59
  array(
60
  'In Queue',
61
  $guid,
62
+ $limit,
63
  )
64
  ),
65
  ARRAY_A
69
  }
70
 
71
  /**
72
+ * Get contact queued emails
73
+ *
74
  * @param int $contact_id
75
+ *
76
  * @return array $queued_emails
77
+ *
78
  * @since 4.7.6
79
  */
80
  public static function get_queued_emails( $contact_id ) {
81
  global $wpdb;
82
 
83
  $queued_emails = $wpdb->get_results(
84
+ $wpdb->prepare(
85
  "SELECT * FROM {$wpdb->prefix}ig_sending_queue WHERE contact_id = %d AND status = %s",
86
  $contact_id,
87
  'In Queue'
110
  if ( ! empty( $id_str ) ) {
111
  if ( 'Sent' === $status ) {
112
  $current_time = ig_get_current_date_time();
113
+ $updated = $wpbd->query(
114
  $wpbd->prepare(
115
  "UPDATE {$wpbd->prefix}ig_sending_queue SET status = %s, sent_at = %s WHERE mailing_queue_id = %d AND contact_id IN($id_str)",
116
  $status,
156
 
157
  global $wpdb;
158
 
159
+ $result = $wpdb->get_var(
160
  $wpdb->prepare(
161
  "SELECT COUNT(*) AS count FROM {$wpdb->prefix}ig_sending_queue WHERE status = %s",
162
  array( 'In Queue' )
163
  )
164
+ );
165
 
166
  return $result;
167
 
207
  if ( $result === $wpdb->prefix . 'es_deliverreport' ) {
208
  $emails = $wpdb->get_results(
209
  $wpdb->prepare(
210
+ "SELECT * FROM {$wpdb->prefix}es_deliverreport WHERE es_deliver_sentguid = %s",
211
+ array( $notification_hash )
212
  ),
213
  ARRAY_A
214
  );
287
 
288
  /**
289
  * Method to insert sending queue data from contact table.
290
+ *
291
+ * @param int $mailing_queue_id Mailing queue ID.
292
+ * @param string $mailing_queue_hash Mailing Hash.
293
+ * @param int $campaign_id Campaign ID.
294
  * @param array|string $list_ids List IDs seperated by commas if string i.e. '1,2,3' or array( 1, 2, 3 ) if array.
295
+ *
296
  * @return bool $is_inserted Is contacts inserted into sending_queue table.
297
+ *
298
  * @since 4.6.4
299
  */
300
  public static function do_insert_from_contacts_table( $mailing_queue_id = 0, $mailing_queue_hash = '', $campaign_id = 0, $list_ids = array() ) {
301
 
302
  global $wpbd;
303
+
304
  $is_inserted = false;
305
+
306
  if ( empty( $mailing_queue_id ) || empty( $mailing_queue_hash ) || empty( $campaign_id ) ) {
307
  return $is_inserted;
308
  }
309
+
310
  $column_defaults = self::get_column_defaults();
311
+
312
  $queue_status = 'In Queue';
313
+ $queue_links = isset( $column_defaults['links'] ) ? $column_defaults['links'] : '';
314
+ $queue_opened = isset( $column_defaults['opened'] ) ? $column_defaults['opened'] : 0;
315
+ $queue_sent_at = isset( $column_defaults['sent_at'] ) ? $column_defaults['sent_at'] : null;
316
  $queue_opened_at = isset( $column_defaults['opened_at'] ) ? $column_defaults['opened_at'] : null;
317
+
318
  $campaign = ES()->campaigns_db->get( $campaign_id );
319
+ $args = array(
320
  'select' => array( 'subscribers.id' ),
321
  'lists' => $list_ids,
322
  'return_sql' => true, // This flag will return the required sql query
323
+ 'orderby' => array( 'id' ),
324
  );
325
  if ( ! empty( $campaign ) && ! empty( $campaign['meta'] ) ) {
326
  $campaign_meta = maybe_unserialize( $campaign['meta'] );
341
  $queue_sent_at,
342
  $queue_opened_at,
343
  );
344
+
345
  $total_contacts_added = $wpbd->query(
346
  $wpbd->prepare(
347
  "INSERT INTO `{$wpbd->prefix}ig_sending_queue`
376
  $query_args
377
  )
378
  );
379
+
380
  // Check if contacts added.
381
  if ( ! empty( $total_contacts_added ) ) {
382
  $is_inserted = true;
383
  ES_DB_Mailing_Queue::update_subscribers_count( $mailing_queue_hash, $total_contacts_added );
384
  } else {
385
+
386
  // If some how above sql query fails then queue emails using old approach.
387
  // i.e. Preparing data for insert query in PHP and then doing insert.
388
+
389
  // Converto to an array if already not an array.
390
  if ( ! is_array( $list_ids ) ) {
391
  $list_ids = explode( ',', $list_ids );
392
  }
393
+
394
  $subscribers = ES()->contacts_db->get_active_contacts_by_list_id( $list_ids );
395
  $subscribers_count = count( $subscribers );
396
  if ( $subscribers_count > 0 ) {
401
  $delivery_data['subscribers'] = $subscribers;
402
  $delivery_data['campaign_id'] = $campaign_id;
403
  $delivery_data['mailing_queue_id'] = $mailing_queue_id;
404
+ $is_inserted = self::do_batch_insert( $delivery_data );
405
  if ( $is_inserted ) {
406
  ES_DB_Mailing_Queue::update_subscribers_count( $mailing_queue_hash, $subscribers_count );
407
  }
408
  }
409
  }
410
+
411
  return $is_inserted;
412
  }
413
 
429
  }
430
 
431
  /*
432
+ * Commenting for now as we might need this function in the future.
433
  public static function migrate_reports_data() {
434
  global $wpdb;
435
 
603
  }
604
  }
605
  */
606
+
607
  public static function delete_records_from_delivereport( $ids ) {
608
  global $wpbd;
609
 
616
 
617
  public static function delete_sending_queue_by_mailing_id( $mailing_queue_ids ) {
618
  global $wpbd;
619
+
620
  $mailing_queue_ids = esc_sql( $mailing_queue_ids );
621
  $mailing_queue_ids = implode( ',', array_map( 'absint', $mailing_queue_ids ) );
622
 
623
  $wpbd->query(
624
+ "DELETE FROM {$wpbd->prefix}ig_sending_queue WHERE mailing_queue_id IN ($mailing_queue_ids)"
625
  );
626
  }
627
 
655
  if ( '' != $hash ) {
656
  $result = $wpdb->get_var(
657
  $wpdb->prepare(
658
+ "SELECT COUNT(*) AS count FROM {$wpdb->prefix}ig_sending_queue WHERE mailing_queue_hash = %s",
659
  array( $hash )
660
  )
661
  );
706
  return $wpbd->get_var( $wpbd->prepare( $query, $args ) );
707
  }
708
 
709
+
710
  /**
711
  * Get Email => ID map based on Sending Queue table
712
+ *
713
+ * @param int $campaign_id
714
  * @param array $emails
715
  *
716
  * @return array
729
 
730
  $emails_str = "'" . implode( "','", $emails ) . "'";
731
 
732
+ $results = $wpbd->get_results(
733
  $wpbd->prepare(
734
+ "SELECT contact_id, email FROM {$wpbd->prefix}ig_sending_queue WHERE campaign_id = %d AND email IN($emails_str)",
735
  $campaign_id
736
+ ),
737
  ARRAY_A
738
  );
739
 
774
 
775
  /**
776
  * Delete contacts from the sending queue
777
+ *
778
  * @param array $contact_ids
779
+ * @param int $message_id
780
+ *
781
+ * @since 4.7.6
782
  */
783
  public static function delete_contacts( $contact_ids, $message_id ) {
784
+
785
  global $wpbd;
786
 
787
  if ( ! empty( $contact_ids ) && ! empty( $message_id ) ) {
lite/includes/db/class-es-db.php CHANGED
@@ -16,7 +16,6 @@ abstract class ES_DB {
16
  *
17
  * @since 4.0.0
18
  * @var $table_name
19
- *
20
  */
21
  public $table_name;
22
 
@@ -25,7 +24,6 @@ abstract class ES_DB {
25
  *
26
  * @since 4.0.0
27
  * @var $version
28
- *
29
  */
30
  public $version;
31
 
@@ -34,7 +32,6 @@ abstract class ES_DB {
34
  *
35
  * @since 4.0.0
36
  * @var $primary_key
37
- *
38
  */
39
  public $primary_key;
40
 
@@ -71,9 +68,9 @@ abstract class ES_DB {
71
  /**
72
  * Retrieve a row by the primary key
73
  *
74
- * @param int $row_id
75
  * @param string $output
76
- * @param false $use_cache
77
  *
78
  * @return false|mixed
79
  *
@@ -111,7 +108,7 @@ abstract class ES_DB {
111
  * @param $column
112
  * @param $row_id
113
  * @param string $output
114
- * @param false $use_cache
115
  *
116
  * @return false|mixed
117
  *
@@ -150,7 +147,7 @@ abstract class ES_DB {
150
  *
151
  * @param string $where
152
  * @param string $output
153
- * @param false $use_cache
154
  *
155
  * @return false|mixed
156
  *
@@ -167,7 +164,6 @@ abstract class ES_DB {
167
  $query .= " WHERE $where";
168
  }
169
 
170
-
171
  if ( true === $use_cache ) {
172
 
173
  // Consider $output also while generating cache key
@@ -204,8 +200,8 @@ abstract class ES_DB {
204
  * Retrieve a specific column's value by the primary key
205
  *
206
  * @param string $column
207
- * @param int $row_id
208
- * @param bool $use_cache
209
  *
210
  * @return null|string|array
211
  *
@@ -259,8 +255,8 @@ abstract class ES_DB {
259
  * @param string $column
260
  * @param string $column_where
261
  * @param string $column_value
262
- * @param bool $only_one
263
- * @param bool $use_cache
264
  *
265
  * @return array|string|null
266
  *
@@ -318,7 +314,7 @@ abstract class ES_DB {
318
  *
319
  * @param string $column
320
  * @param string $where
321
- * @param bool $use_cache
322
  *
323
  * @return array
324
  *
@@ -349,7 +345,6 @@ abstract class ES_DB {
349
 
350
  $this->set_cache( $cache_key, $result );
351
  }
352
-
353
  } else {
354
  $result = $wpbd->get_col( $query );
355
  }
@@ -360,10 +355,10 @@ abstract class ES_DB {
360
  /**
361
  * Select few columns based on condition
362
  *
363
- * @param array $columns
364
  * @param string $where
365
  * @param string $output
366
- * @param bool $use_cache
367
  *
368
  * @return array|object|null
369
  *
@@ -450,7 +445,7 @@ abstract class ES_DB {
450
  * Update a specific row
451
  *
452
  * @param $row_id
453
- * @param array $data
454
  * @param string $where
455
  *
456
  * @return bool
@@ -602,7 +597,7 @@ abstract class ES_DB {
602
  * Get total count
603
  *
604
  * @param string $where
605
- * @param bool $use_cache
606
  *
607
  * @return string|null
608
  *
@@ -643,7 +638,7 @@ abstract class ES_DB {
643
  * Insert data into bulk
644
  *
645
  * @param array $values
646
- * @param int $length
647
  *
648
  * @since 4.2.1
649
  *
@@ -705,9 +700,9 @@ abstract class ES_DB {
705
  $fields_str = '`' . implode( '`, `', $fields ) . '`';
706
  }
707
 
708
- $query = "INSERT INTO $this->table_name ({$fields_str}) VALUES ";
709
  $query .= implode( ', ', $place_holders );
710
- $sql = $wpbd->prepare( $query, $final_values );
711
 
712
  if ( ! $wpbd->query( $sql ) ) {
713
  $error_flag = true;
@@ -731,16 +726,15 @@ abstract class ES_DB {
731
  * @param $values
732
  *
733
  * @return bool
734
- *
735
  */
736
  public static function do_insert( $table_name, $fields, $place_holders, $values ) {
737
  global $wpbd;
738
 
739
  $fields_str = '`' . implode( '`, `', $fields ) . '`';
740
 
741
- $query = "INSERT INTO $table_name ({$fields_str}) VALUES ";
742
  $query .= implode( ', ', $place_holders );
743
- $sql = $wpbd->prepare( $query, $values );
744
 
745
  if ( $wpbd->query( $sql ) ) {
746
  return true;
@@ -814,7 +808,7 @@ abstract class ES_DB {
814
 
815
  return array(
816
  'data' => $data,
817
- 'column_formats' => $column_formats
818
  );
819
 
820
  }
16
  *
17
  * @since 4.0.0
18
  * @var $table_name
 
19
  */
20
  public $table_name;
21
 
24
  *
25
  * @since 4.0.0
26
  * @var $version
 
27
  */
28
  public $version;
29
 
32
  *
33
  * @since 4.0.0
34
  * @var $primary_key
 
35
  */
36
  public $primary_key;
37
 
68
  /**
69
  * Retrieve a row by the primary key
70
  *
71
+ * @param int $row_id
72
  * @param string $output
73
+ * @param false $use_cache
74
  *
75
  * @return false|mixed
76
  *
108
  * @param $column
109
  * @param $row_id
110
  * @param string $output
111
+ * @param false $use_cache
112
  *
113
  * @return false|mixed
114
  *
147
  *
148
  * @param string $where
149
  * @param string $output
150
+ * @param false $use_cache
151
  *
152
  * @return false|mixed
153
  *
164
  $query .= " WHERE $where";
165
  }
166
 
 
167
  if ( true === $use_cache ) {
168
 
169
  // Consider $output also while generating cache key
200
  * Retrieve a specific column's value by the primary key
201
  *
202
  * @param string $column
203
+ * @param int $row_id
204
+ * @param bool $use_cache
205
  *
206
  * @return null|string|array
207
  *
255
  * @param string $column
256
  * @param string $column_where
257
  * @param string $column_value
258
+ * @param bool $only_one
259
+ * @param bool $use_cache
260
  *
261
  * @return array|string|null
262
  *
314
  *
315
  * @param string $column
316
  * @param string $where
317
+ * @param bool $use_cache
318
  *
319
  * @return array
320
  *
345
 
346
  $this->set_cache( $cache_key, $result );
347
  }
 
348
  } else {
349
  $result = $wpbd->get_col( $query );
350
  }
355
  /**
356
  * Select few columns based on condition
357
  *
358
+ * @param array $columns
359
  * @param string $where
360
  * @param string $output
361
+ * @param bool $use_cache
362
  *
363
  * @return array|object|null
364
  *
445
  * Update a specific row
446
  *
447
  * @param $row_id
448
+ * @param array $data
449
  * @param string $where
450
  *
451
  * @return bool
597
  * Get total count
598
  *
599
  * @param string $where
600
+ * @param bool $use_cache
601
  *
602
  * @return string|null
603
  *
638
  * Insert data into bulk
639
  *
640
  * @param array $values
641
+ * @param int $length
642
  *
643
  * @since 4.2.1
644
  *
700
  $fields_str = '`' . implode( '`, `', $fields ) . '`';
701
  }
702
 
703
+ $query = "INSERT INTO $this->table_name ({$fields_str}) VALUES ";
704
  $query .= implode( ', ', $place_holders );
705
+ $sql = $wpbd->prepare( $query, $final_values );
706
 
707
  if ( ! $wpbd->query( $sql ) ) {
708
  $error_flag = true;
726
  * @param $values
727
  *
728
  * @return bool
 
729
  */
730
  public static function do_insert( $table_name, $fields, $place_holders, $values ) {
731
  global $wpbd;
732
 
733
  $fields_str = '`' . implode( '`, `', $fields ) . '`';
734
 
735
+ $query = "INSERT INTO $table_name ({$fields_str}) VALUES ";
736
  $query .= implode( ', ', $place_holders );
737
+ $sql = $wpbd->prepare( $query, $values );
738
 
739
  if ( $wpbd->query( $sql ) ) {
740
  return true;
808
 
809
  return array(
810
  'data' => $data,
811
+ 'column_formats' => $column_formats,
812
  );
813
 
814
  }
lite/includes/db/class-ig-es-db-unsubscribe-feedback.php CHANGED
@@ -10,7 +10,6 @@ class IG_ES_DB_Unsubscribe_Feedback extends ES_DB {
10
  *
11
  * @since 4.6.8
12
  * @var $table_name
13
- *
14
  */
15
  public $table_name;
16
 
@@ -19,7 +18,6 @@ class IG_ES_DB_Unsubscribe_Feedback extends ES_DB {
19
  *
20
  * @since 4.6.8
21
  * @var $version
22
- *
23
  */
24
  public $version;
25
 
@@ -28,7 +26,6 @@ class IG_ES_DB_Unsubscribe_Feedback extends ES_DB {
28
  *
29
  * @since 4.6.8
30
  * @var $primary_key
31
- *
32
  */
33
  public $primary_key;
34
 
@@ -76,7 +73,7 @@ class IG_ES_DB_Unsubscribe_Feedback extends ES_DB {
76
  * Get default column values
77
  *
78
  * @return array Default column values
79
- *
80
  * @since 4.6.8
81
  */
82
  public function get_column_defaults() {
@@ -89,7 +86,7 @@ class IG_ES_DB_Unsubscribe_Feedback extends ES_DB {
89
  'feedback_text' => '',
90
  'created_at' => ig_get_current_date_time(),
91
  'updated_at' => ig_get_current_date_time(),
92
- 'meta' => '',
93
  );
94
  }
95
 
@@ -116,7 +113,6 @@ class IG_ES_DB_Unsubscribe_Feedback extends ES_DB {
116
  * @param array $feedback_data Feedback data.
117
  *
118
  * @return bool|void
119
- *
120
  */
121
  public function update_feedback( $feedback_id = 0, $feedback_data = array() ) {
122
 
@@ -129,10 +125,10 @@ class IG_ES_DB_Unsubscribe_Feedback extends ES_DB {
129
 
130
  /**
131
  * Get existing feedback for given contact and list id
132
- *
133
  * @param int $contact_id Contact id
134
  * @param int $list_id List id
135
- *
136
  * @return int $existing_feedback_id Existing feedback ID
137
  */
138
  public function get_existing_feedback_id( $contact_id = 0, $list_id = 0 ) {
@@ -143,7 +139,7 @@ class IG_ES_DB_Unsubscribe_Feedback extends ES_DB {
143
  if ( empty( $contact_id ) || empty( $list_id ) ) {
144
  return $existing_feedback_id;
145
  }
146
-
147
  $existing_feedback_id = $wpdb->get_var(
148
  $wpdb->prepare(
149
  "SELECT id FROM {$wpdb->prefix}ig_unsubscribe_feedback WHERE `contact_id`= %d AND `list_id` = %d ORDER BY updated_at DESC LIMIT 1",
10
  *
11
  * @since 4.6.8
12
  * @var $table_name
 
13
  */
14
  public $table_name;
15
 
18
  *
19
  * @since 4.6.8
20
  * @var $version
 
21
  */
22
  public $version;
23
 
26
  *
27
  * @since 4.6.8
28
  * @var $primary_key
 
29
  */
30
  public $primary_key;
31
 
73
  * Get default column values
74
  *
75
  * @return array Default column values
76
+ *
77
  * @since 4.6.8
78
  */
79
  public function get_column_defaults() {
86
  'feedback_text' => '',
87
  'created_at' => ig_get_current_date_time(),
88
  'updated_at' => ig_get_current_date_time(),
89
+ 'meta' => '',
90
  );
91
  }
92
 
113
  * @param array $feedback_data Feedback data.
114
  *
115
  * @return bool|void
 
116
  */
117
  public function update_feedback( $feedback_id = 0, $feedback_data = array() ) {
118
 
125
 
126
  /**
127
  * Get existing feedback for given contact and list id
128
+ *
129
  * @param int $contact_id Contact id
130
  * @param int $list_id List id
131
+ *
132
  * @return int $existing_feedback_id Existing feedback ID
133
  */
134
  public function get_existing_feedback_id( $contact_id = 0, $list_id = 0 ) {
139
  if ( empty( $contact_id ) || empty( $list_id ) ) {
140
  return $existing_feedback_id;
141
  }
142
+
143
  $existing_feedback_id = $wpdb->get_var(
144
  $wpdb->prepare(
145
  "SELECT id FROM {$wpdb->prefix}ig_unsubscribe_feedback WHERE `contact_id`= %d AND `list_id` = %d ORDER BY updated_at DESC LIMIT 1",
lite/includes/db/class-ig-es-db-wc-cart.php CHANGED
@@ -15,14 +15,14 @@ if ( ! defined( 'ABSPATH' ) ) {
15
  /**
16
  * IG_ES_DB_WC_Cart class
17
  *
18
- *@since 4.6.5
19
  */
20
  class IG_ES_DB_WC_Cart extends ES_DB {
21
 
22
  /**
23
  * Workflow queue table name
24
  *
25
- *@since 4.6.5
26
  * @var $table_name
27
  */
28
  public $table_name;
@@ -30,7 +30,7 @@ class IG_ES_DB_WC_Cart extends ES_DB {
30
  /**
31
  * Workflow queue table version
32
  *
33
- *@since 4.6.5
34
  * @var $version
35
  */
36
  public $version;
@@ -38,7 +38,7 @@ class IG_ES_DB_WC_Cart extends ES_DB {
38
  /**
39
  * Workflow queue table primary key
40
  *
41
- *@since 4.6.5
42
  * @var $primary_key
43
  */
44
  public $primary_key;
@@ -46,7 +46,7 @@ class IG_ES_DB_WC_Cart extends ES_DB {
46
  /**
47
  * IG_ES_DB_WC_Cart constructor.
48
  *
49
- *@since 4.6.5
50
  */
51
  public function __construct() {
52
  global $wpdb;
@@ -62,7 +62,7 @@ class IG_ES_DB_WC_Cart extends ES_DB {
62
  /**
63
  * Returns workflow queue table's columns
64
  *
65
- *@since 4.6.5
66
  *
67
  * @return array workflow queue table columns
68
  */
@@ -88,7 +88,7 @@ class IG_ES_DB_WC_Cart extends ES_DB {
88
  /**
89
  * Returns default values for workflow columns
90
  *
91
- *@since 4.6.5
92
  *
93
  * @return array default values for workflow columns
94
  */
@@ -120,7 +120,7 @@ class IG_ES_DB_WC_Cart extends ES_DB {
120
  *
121
  * @return mixed $result Query result
122
  *
123
- *@since 4.6.5
124
  */
125
  public function get_carts( $query_args = array(), $output = ARRAY_A, $do_count_only = false ) {
126
 
15
  /**
16
  * IG_ES_DB_WC_Cart class
17
  *
18
+ * @since 4.6.5
19
  */
20
  class IG_ES_DB_WC_Cart extends ES_DB {
21
 
22
  /**
23
  * Workflow queue table name
24
  *
25
+ * @since 4.6.5
26
  * @var $table_name
27
  */
28
  public $table_name;
30
  /**
31
  * Workflow queue table version
32
  *
33
+ * @since 4.6.5
34
  * @var $version
35
  */
36
  public $version;
38
  /**
39
  * Workflow queue table primary key
40
  *
41
+ * @since 4.6.5
42
  * @var $primary_key
43
  */
44
  public $primary_key;
46
  /**
47
  * IG_ES_DB_WC_Cart constructor.
48
  *
49
+ * @since 4.6.5
50
  */
51
  public function __construct() {
52
  global $wpdb;
62
  /**
63
  * Returns workflow queue table's columns
64
  *
65
+ * @since 4.6.5
66
  *
67
  * @return array workflow queue table columns
68
  */
88
  /**
89
  * Returns default values for workflow columns
90
  *
91
+ * @since 4.6.5
92
  *
93
  * @return array default values for workflow columns
94
  */
120
  *
121
  * @return mixed $result Query result
122
  *
123
+ * @since 4.6.5
124
  */
125
  public function get_carts( $query_args = array(), $output = ARRAY_A, $do_count_only = false ) {
126
 
lite/includes/db/class-ig-es-db-wc-guest.php CHANGED
@@ -15,14 +15,14 @@ if ( ! defined( 'ABSPATH' ) ) {
15
  /**
16
  * IG_ES_DB_WC_Guest class
17
  *
18
- *@since 4.6.5
19
  */
20
  class IG_ES_DB_WC_Guest extends ES_DB {
21
 
22
  /**
23
  * Guest queue table name
24
  *
25
- *@since 4.6.5
26
  * @var $table_name
27
  */
28
  public $table_name;
@@ -30,7 +30,7 @@ class IG_ES_DB_WC_Guest extends ES_DB {
30
  /**
31
  * Guest queue table version
32
  *
33
- *@since 4.6.5
34
  * @var $version
35
  */
36
  public $version;
@@ -38,7 +38,7 @@ class IG_ES_DB_WC_Guest extends ES_DB {
38
  /**
39
  * Guest queue table primary key
40
  *
41
- *@since 4.6.5
42
  * @var $primary_key
43
  */
44
  public $primary_key;
@@ -46,7 +46,7 @@ class IG_ES_DB_WC_Guest extends ES_DB {
46
  /**
47
  * IG_ES_DB_WC_Guest constructor.
48
  *
49
- *@since 4.6.5
50
  */
51
  public function __construct() {
52
  global $wpdb;
@@ -62,7 +62,7 @@ class IG_ES_DB_WC_Guest extends ES_DB {
62
  /**
63
  * Returns Guest queue table's columns
64
  *
65
- *@since 4.6.5
66
  *
67
  * @return array Guest queue table columns
68
  */
@@ -83,7 +83,7 @@ class IG_ES_DB_WC_Guest extends ES_DB {
83
  /**
84
  * Returns default values for Guest columns
85
  *
86
- *@since 4.6.5
87
  *
88
  * @return array default values for Guest columns
89
  */
@@ -110,7 +110,7 @@ class IG_ES_DB_WC_Guest extends ES_DB {
110
  *
111
  * @return mixed $result Query result
112
  *
113
- *@since 4.6.5
114
  */
115
  public function get_carts( $query_args = array(), $output = ARRAY_A, $do_count_only = false ) {
116
 
15
  /**
16
  * IG_ES_DB_WC_Guest class
17
  *
18
+ * @since 4.6.5
19
  */
20
  class IG_ES_DB_WC_Guest extends ES_DB {
21
 
22
  /**
23
  * Guest queue table name
24
  *
25
+ * @since 4.6.5
26
  * @var $table_name
27
  */
28
  public $table_name;
30
  /**
31
  * Guest queue table version
32
  *
33
+ * @since 4.6.5
34
  * @var $version
35
  */
36
  public $version;
38
  /**
39
  * Guest queue table primary key
40
  *
41
+ * @since 4.6.5
42
  * @var $primary_key
43
  */
44
  public $primary_key;
46
  /**
47
  * IG_ES_DB_WC_Guest constructor.
48
  *
49
+ * @since 4.6.5
50
  */
51
  public function __construct() {
52
  global $wpdb;
62
  /**
63
  * Returns Guest queue table's columns
64
  *
65
+ * @since 4.6.5
66
  *
67
  * @return array Guest queue table columns
68
  */
83
  /**
84
  * Returns default values for Guest columns
85
  *
86
+ * @since 4.6.5
87
  *
88
  * @return array default values for Guest columns
89
  */
110
  *
111
  * @return mixed $result Query result
112
  *
113
+ * @since 4.6.5
114
  */
115
  public function get_carts( $query_args = array(), $output = ARRAY_A, $do_count_only = false ) {
116
 
lite/includes/es-backward.php CHANGED
@@ -91,7 +91,7 @@ class es_cls_dbquery {
91
  'email' => $email,
92
  'contact_id' => $contact_id,
93
  'guid' => $guid,
94
- 'list_name' => $list_name
95
  );
96
 
97
  if ( 1 == $optin_type ) {
@@ -105,7 +105,7 @@ class es_cls_dbquery {
105
  'first_name' => $sub_data['first_name'],
106
  'last_name' => $sub_data['last_name'],
107
  'email' => $email,
108
- 'list_name' => $list_name
109
  );
110
 
111
  ES()->mailer->send_add_new_contact_notification_to_admins( $template_data );
@@ -114,7 +114,6 @@ class es_cls_dbquery {
114
  // Send Confirmation mail
115
  ES()->mailer->send_double_optin_email( $email, $data );
116
  }
117
-
118
  }
119
  }
120
 
91
  'email' => $email,
92
  'contact_id' => $contact_id,
93
  'guid' => $guid,
94
+ 'list_name' => $list_name,
95
  );
96
 
97
  if ( 1 == $optin_type ) {
105
  'first_name' => $sub_data['first_name'],
106
  'last_name' => $sub_data['last_name'],
107
  'email' => $email,
108
+ 'list_name' => $list_name,
109
  );
110
 
111
  ES()->mailer->send_add_new_contact_notification_to_admins( $template_data );
114
  // Send Confirmation mail
115
  ES()->mailer->send_double_optin_email( $email, $data );
116
  }
 
117
  }
118
  }
119
 
lite/includes/es-core-functions.php CHANGED
@@ -54,7 +54,6 @@ if ( ! function_exists( 'get_ig_logger' ) ) {
54
  * Get IG Logger
55
  *
56
  * @return IG_Logger|string|null
57
- *
58
  */
59
  function get_ig_logger() {
60
 
@@ -138,7 +137,7 @@ if ( ! function_exists( 'ig_es_format_date_time' ) ) {
138
  */
139
  function ig_es_format_date_time( $date ) {
140
 
141
- $local_timestamp = ( '0000-00-00 00:00:00' !== $date && ! empty( $date ) ) ? ES_Common::convert_date_to_wp_date( get_date_from_gmt( $date )) : '<i class="dashicons dashicons-es dashicons-minus"></i>';
142
 
143
  return $local_timestamp;
144
  }
@@ -200,17 +199,17 @@ if ( ! function_exists( 'ig_es_get_data' ) ) {
200
  /**
201
  * Get data from array
202
  *
203
- * @param array $array
204
  * @param string $var
205
  * @param string $default
206
- * @param bool $clean
207
  *
208
  * @return array|string
209
  *
210
  * @since 4.1.15
211
  */
212
  function ig_es_get_data( $array = array(), $var = '', $default = '', $clean = false ) {
213
-
214
  if ( ! empty( $var ) ) {
215
  $value = isset( $array[ $var ] ) ? wp_unslash( $array[ $var ] ) : $default;
216
  } else {
@@ -252,11 +251,11 @@ if ( ! function_exists( 'ig_es_get_post_data' ) ) {
252
  */
253
 
254
  function ig_es_get_post_data( $var = '', $default = '', $clean = true ) {
255
-
256
  $nonce = ! empty( $_POST['es-nonce'] ) ? sanitize_text_field( $_POST['es-nonce'] ) : '';
257
-
258
  if ( wp_verify_nonce( $nonce, 'es-nonce' ) ) {
259
- //TODO: Verify Nonce
260
  $nonce_verified = true;
261
  }
262
 
@@ -278,7 +277,7 @@ if ( ! function_exists( 'ig_es_get_ip' ) ) {
278
  if ( isset( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) {
279
  $ip = sanitize_text_field( $_SERVER['HTTP_CF_CONNECTING_IP'] );
280
  } elseif ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) {
281
- $ip = sanitize_text_field( $_SERVER['HTTP_X_REAL_IP'] );
282
  } elseif ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
283
  $ip = sanitize_text_field( $_SERVER['HTTP_CLIENT_IP'] );
284
  } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
@@ -412,7 +411,7 @@ if ( ! function_exists( 'ig_es_get_upcoming_weekly_datetime' ) ) {
412
  3 => 'wednesday',
413
  4 => 'thursday',
414
  5 => 'friday',
415
- 6 => 'saturday'
416
  );
417
 
418
  // w is used since it returns day number considering Sunday as 0.
@@ -424,7 +423,7 @@ if ( ! function_exists( 'ig_es_get_upcoming_weekly_datetime' ) ) {
424
  $current_hours = (int) current_time( 'H' );
425
  $current_minutes = (int) current_time( 'i' );
426
  $current_seconds = (int) current_time( 's' );
427
-
428
  $current_time = $current_hours * HOUR_IN_SECONDS + $current_minutes * MINUTE_IN_SECONDS + $current_seconds;
429
 
430
  // Check if campaign time has not yet passed then we can use today's date/time else use date/time when campaign day comes next time.
@@ -481,8 +480,8 @@ if ( ! function_exists( 'ig_es_get_next_future_schedule_date' ) ) {
481
  * @param $utc_start
482
  * @param $interval
483
  * @param $time_frame
484
- * @param array $weekdays
485
- * @param bool $in_future
486
  *
487
  * @return false|float|int
488
  *
@@ -532,28 +531,28 @@ if ( ! function_exists( 'ig_es_get_next_future_schedule_date' ) ) {
532
  $time_frame = 'day';
533
  $next_date = $now;
534
  $interval = 1;
535
- $count = 1;
536
  $change_next_date = false;
537
  break;
538
  case 'daily':
539
  $time_frame = 'day';
540
  $next_date = ig_es_get_upcoming_daily_datetime( $time_of_day );
541
  $interval = 1;
542
- $count = 1;
543
  $change_next_date = false;
544
  break;
545
  case 'weekly':
546
  $time_frame = 'day';
547
  $next_date = ig_es_get_upcoming_weekly_datetime( $interval, $time_of_day );
548
- $interval = 1;
549
- $count = 1;
550
  $change_next_date = false;
551
  break;
552
  case 'monthly':
553
  $time_frame = 'day';
554
  $next_date = ig_es_get_upcoming_monthly_datetime( $interval, $time_of_day );
555
- $interval = 1;
556
- $count = 1;
557
  $change_next_date = false;
558
  break;
559
  default:
@@ -635,11 +634,11 @@ if ( ! function_exists( 'ig_es_array_insert_after' ) ) {
635
  if ( ! function_exists( 'ig_es_get_raw_human_interval' ) ) {
636
  /**
637
  * Gets interval split by days, hours, minutes and seconds
638
- *
639
  * @param $interval_in_seconds
640
- *
641
  * @return array
642
- *
643
  * @since 4.4.9
644
  */
645
  function ig_es_get_raw_human_interval( $interval_in_seconds = 0 ) {
@@ -673,11 +672,11 @@ if ( ! function_exists( 'ig_es_get_raw_human_interval' ) ) {
673
  if ( ! function_exists( 'ig_es_get_human_interval' ) ) {
674
  /**
675
  * Gets interval in human readable format
676
- *
677
  * @param $interval_in_seconds
678
- *
679
  * @return string
680
- *
681
  * @since 4.4.9
682
  */
683
  function ig_es_get_human_interval( $interval_in_seconds = 0 ) {
@@ -718,133 +717,133 @@ if ( ! function_exists( 'ig_es_allowed_html_tags_in_esc' ) ) {
718
  * @since 4.5.4
719
  */
720
  function ig_es_allowed_html_tags_in_esc() {
721
- $context_allowed_tags = wp_kses_allowed_html('post');
722
- $custom_allowed_tags = array(
723
- 'div' => array(
724
- 'x-data' => true,
725
- 'x-show' => true,
726
- ),
727
- 'select' => array(
728
- 'class' => true,
729
- 'name' => true,
730
- 'id' => true,
731
- 'style' => true,
732
- 'title' => true,
733
- 'role' => true,
734
- 'data-*' => true,
735
- 'tab-*' => true,
736
- 'multiple' => true,
737
- 'aria-*' => true,
738
- 'disabled' => true,
739
- ),
740
- 'optgroup' => array(
741
- 'label' => true,
742
- ),
743
- 'option' => array(
744
- 'class' => true,
745
- 'value' => true,
746
- 'selected' => true,
747
- 'name' => true,
748
- 'id' => true,
749
- 'style' => true,
750
- 'title' => true,
751
- 'data-*' => true,
752
- ),
753
- 'input' => array(
754
- 'class' => true,
755
- 'name' => true,
756
- 'type' => true,
757
- 'value' => true,
758
- 'id' => true,
759
- 'checked' => true,
760
- 'disabled' => true,
761
- 'selected' => true,
762
- 'style' => true,
763
- 'required' => 'required',
764
- 'min' => true,
765
- 'max' => true,
766
- 'maxlength' => true,
767
- 'size' => true,
768
- 'placeholder' => true,
769
- 'autocomplete' => true,
770
- 'autocapitalize'=> true,
771
- 'autocorrect' => true,
772
- 'tabindex' => true,
773
- 'role' => true,
774
- 'aria-*' => true,
775
- 'data-*' => true,
776
- ),
777
- 'label' => array(
778
- 'class' => true,
779
- 'name' => true,
780
- 'type' => true,
781
- 'value' => true,
782
- 'id' => true,
783
- 'for' => true,
784
- 'style' => true,
785
- ),
786
- 'form' => array(
787
- 'class' => true,
788
- 'name' => true,
789
- 'value' => true,
790
- 'id' => true,
791
- 'style' => true,
792
- 'action' => true,
793
- 'method' => true,
794
- ),
795
- 'svg' => array(
796
- 'width' => true,
797
- 'height' => true,
798
- 'viewbox' => true,
799
- 'xmlns' => true,
800
- 'class' => true,
801
- 'stroke-*' => true,
802
- 'fill' => true,
803
- 'stroke' => true,
804
- ),
805
- 'path' => array(
806
- 'd' => true,
807
- 'fill' => true,
808
- 'class' => true,
809
- 'fill-*' => true,
810
- 'clip-*' => true,
811
- 'stroke-linecap' => true,
812
- 'stroke-linejoin' => true,
813
- 'stroke-width' => true,
814
- 'fill-rule' => true,
815
- ),
816
-
817
- 'main' => array(
818
- 'align' => true,
819
- 'dir' => true,
820
- 'lang' => true,
821
- 'xml:lang' => true,
822
- 'aria-*' => true,
823
- 'class' => true,
824
- 'id' => true,
825
- 'style' => true,
826
- 'title' => true,
827
- 'role' => true,
828
- 'data-*' => true,
829
- ),
830
- 'textarea' => array(
831
- 'autocomplete' => true,
832
- ),
833
- 'style' => array(),
834
- 'link' => array(
835
- 'rel' => true,
836
- 'id' => true,
837
- 'href' => true,
838
- 'media' => true,
839
- ),
840
- 'a' => array(
841
- 'x-on:click' => true,
842
- ),
843
- 'polygon' => array(
844
- 'class' => true,
845
- 'points' => true,
846
- )
847
- );
848
 
849
  $allowedtags = array_merge_recursive( $context_allowed_tags, $custom_allowed_tags );
850
 
@@ -857,7 +856,7 @@ if ( ! function_exists( 'ig_es_allowed_css_style' ) ) {
857
  * Allow CSS style in WP Kses
858
  *
859
  * @since 4.5.4
860
- *
861
  * @since 4.7.3 Returns empty array to whitelist all CSS properties.
862
  */
863
  function ig_es_allowed_css_style( $default_allowed_attr ) {
@@ -866,7 +865,7 @@ if ( ! function_exists( 'ig_es_allowed_css_style' ) ) {
866
  }
867
 
868
  if ( ! function_exists( 'ig_es_increase_memory_limit' ) ) {
869
-
870
  /**
871
  * Return memory limit required for ES heavy operations
872
  *
@@ -881,14 +880,14 @@ if ( ! function_exists( 'ig_es_increase_memory_limit' ) ) {
881
  }
882
 
883
  if ( ! function_exists( 'ig_es_remove_utf8_bom' ) ) {
884
-
885
  /**
886
  * Remove UTF-8 BOM signature.
887
  *
888
  * @param string $string String to handle.
889
  *
890
  * @return string
891
- *
892
  * @since 4.5.4
893
  */
894
  function ig_es_remove_utf8_bom( $string = '' ) {
@@ -904,19 +903,19 @@ if ( ! function_exists( 'ig_es_remove_utf8_bom' ) ) {
904
  }
905
 
906
  if ( ! function_exists( 'ig_es_covert_to_utf8_encoding' ) ) {
907
-
908
  /**
909
  * Function to convert existing string to its UTF-8 equivalent string.
910
  *
911
  * @param string $data String to handle.
912
- * @param bool $use_mb Flag to determine whether we should use mb_* functions while detecting and converting the encoding.
913
  *
914
  * @return string $data
915
- *
916
  * @since 4.5.6
917
  */
918
  function ig_es_covert_to_utf8_encoding( $data = '', $use_mb = false ) {
919
-
920
  // Check if we can use mb_* functions.
921
  if ( $use_mb ) {
922
  // Detect character encoding. detecting order is 1.UTF-8 2. ISO-8859-1.
@@ -940,14 +939,14 @@ if ( ! function_exists( 'ig_es_covert_to_utf8_encoding' ) ) {
940
  if ( ! function_exists( 'ig_es_insert_widget_in_sidebar' ) ) {
941
  /**
942
  * Insert a widget in a sidebar.
943
- *
944
  * @param string $widget_id ID of the widget (search, recent-posts, etc.)
945
- * @param array $widget_data Widget settings.
946
  * @param string $sidebar ID of the sidebar.
947
  * @param string $allow_duplicate Flag to check whether we should add widget even if added to the sidebar already.
948
- *
949
  * @return boolean
950
- *
951
  * @since 4.6.0
952
  */
953
  function ig_es_insert_widget_in_sidebar( $widget_id, $widget_data, $sidebar, $allow_duplicate = false ) {
@@ -977,20 +976,20 @@ if ( ! function_exists( 'ig_es_insert_widget_in_sidebar' ) ) {
977
  // Add new widget only if it already not added in the sidebar or duplicate widget is allowed.
978
  if ( ! $widget_already_added || $allow_duplicate ) {
979
  $next_key = $numeric_keys ? max( $numeric_keys ) + 1 : 1;
980
-
981
  // Add this widget to the sidebar
982
  $sidebars_widgets[ $sidebar ][] = $widget_id . '-' . $next_key;
983
-
984
  // Add the new widget instance
985
  $widget_instances[ $next_key ] = $widget_data;
986
-
987
  // Store updated sidebars, widgets and their instances
988
  update_option( 'sidebars_widgets', $sidebars_widgets );
989
  update_option( 'widget_' . $widget_id, $widget_instances );
990
 
991
  return true;
992
  }
993
-
994
  return false;
995
  }
996
  }
54
  * Get IG Logger
55
  *
56
  * @return IG_Logger|string|null
 
57
  */
58
  function get_ig_logger() {
59
 
137
  */
138
  function ig_es_format_date_time( $date ) {
139
 
140
+ $local_timestamp = ( '0000-00-00 00:00:00' !== $date && ! empty( $date ) ) ? ES_Common::convert_date_to_wp_date( get_date_from_gmt( $date ) ) : '<i class="dashicons dashicons-es dashicons-minus"></i>';
141
 
142
  return $local_timestamp;
143
  }
199
  /**
200
  * Get data from array
201
  *
202
+ * @param array $array
203
  * @param string $var
204
  * @param string $default
205
+ * @param bool $clean
206
  *
207
  * @return array|string
208
  *
209
  * @since 4.1.15
210
  */
211
  function ig_es_get_data( $array = array(), $var = '', $default = '', $clean = false ) {
212
+
213
  if ( ! empty( $var ) ) {
214
  $value = isset( $array[ $var ] ) ? wp_unslash( $array[ $var ] ) : $default;
215
  } else {
251
  */
252
 
253
  function ig_es_get_post_data( $var = '', $default = '', $clean = true ) {
254
+
255
  $nonce = ! empty( $_POST['es-nonce'] ) ? sanitize_text_field( $_POST['es-nonce'] ) : '';
256
+
257
  if ( wp_verify_nonce( $nonce, 'es-nonce' ) ) {
258
+ // TODO: Verify Nonce
259
  $nonce_verified = true;
260
  }
261
 
277
  if ( isset( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) {
278
  $ip = sanitize_text_field( $_SERVER['HTTP_CF_CONNECTING_IP'] );
279
  } elseif ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) {
280
+ $ip = sanitize_text_field( $_SERVER['HTTP_X_REAL_IP'] );
281
  } elseif ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
282
  $ip = sanitize_text_field( $_SERVER['HTTP_CLIENT_IP'] );
283
  } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
411
  3 => 'wednesday',
412
  4 => 'thursday',
413
  5 => 'friday',
414
+ 6 => 'saturday',
415
  );
416
 
417
  // w is used since it returns day number considering Sunday as 0.
423
  $current_hours = (int) current_time( 'H' );
424
  $current_minutes = (int) current_time( 'i' );
425
  $current_seconds = (int) current_time( 's' );
426
+
427
  $current_time = $current_hours * HOUR_IN_SECONDS + $current_minutes * MINUTE_IN_SECONDS + $current_seconds;
428
 
429
  // Check if campaign time has not yet passed then we can use today's date/time else use date/time when campaign day comes next time.
480
  * @param $utc_start
481
  * @param $interval
482
  * @param $time_frame
483
+ * @param array $weekdays
484
+ * @param bool $in_future
485
  *
486
  * @return false|float|int
487
  *
531
  $time_frame = 'day';
532
  $next_date = $now;
533
  $interval = 1;
534
+ $count = 1;
535
  $change_next_date = false;
536
  break;
537
  case 'daily':
538
  $time_frame = 'day';
539
  $next_date = ig_es_get_upcoming_daily_datetime( $time_of_day );
540
  $interval = 1;
541
+ $count = 1;
542
  $change_next_date = false;
543
  break;
544
  case 'weekly':
545
  $time_frame = 'day';
546
  $next_date = ig_es_get_upcoming_weekly_datetime( $interval, $time_of_day );
547
+ $interval = 1;
548
+ $count = 1;
549
  $change_next_date = false;
550
  break;
551
  case 'monthly':
552
  $time_frame = 'day';
553
  $next_date = ig_es_get_upcoming_monthly_datetime( $interval, $time_of_day );
554
+ $interval = 1;
555
+ $count = 1;
556
  $change_next_date = false;
557
  break;
558
  default:
634
  if ( ! function_exists( 'ig_es_get_raw_human_interval' ) ) {
635
  /**
636
  * Gets interval split by days, hours, minutes and seconds
637
+ *
638
  * @param $interval_in_seconds
639
+ *
640
  * @return array
641
+ *
642
  * @since 4.4.9
643
  */
644
  function ig_es_get_raw_human_interval( $interval_in_seconds = 0 ) {
672
  if ( ! function_exists( 'ig_es_get_human_interval' ) ) {
673
  /**
674
  * Gets interval in human readable format
675
+ *
676
  * @param $interval_in_seconds
677
+ *
678
  * @return string
679
+ *
680
  * @since 4.4.9
681
  */
682
  function ig_es_get_human_interval( $interval_in_seconds = 0 ) {
717
  * @since 4.5.4
718
  */
719
  function ig_es_allowed_html_tags_in_esc() {
720
+ $context_allowed_tags = wp_kses_allowed_html( 'post' );
721
+ $custom_allowed_tags = array(
722
+ 'div' => array(
723
+ 'x-data' => true,
724
+ 'x-show' => true,
725
+ ),
726
+ 'select' => array(
727
+ 'class' => true,
728
+ 'name' => true,
729
+ 'id' => true,
730
+ 'style' => true,
731
+ 'title' => true,
732
+ 'role' => true,
733
+ 'data-*' => true,
734
+ 'tab-*' => true,
735
+ 'multiple' => true,
736
+ 'aria-*' => true,
737
+ 'disabled' => true,
738
+ ),
739
+ 'optgroup' => array(
740
+ 'label' => true,
741
+ ),
742
+ 'option' => array(
743
+ 'class' => true,
744
+ 'value' => true,
745
+ 'selected' => true,
746
+ 'name' => true,
747
+ 'id' => true,
748
+ 'style' => true,
749
+ 'title' => true,
750
+ 'data-*' => true,
751
+ ),
752
+ 'input' => array(
753
+ 'class' => true,
754
+ 'name' => true,
755
+ 'type' => true,
756
+ 'value' => true,
757
+ 'id' => true,
758
+ 'checked' => true,
759
+ 'disabled' => true,
760
+ 'selected' => true,
761
+ 'style' => true,
762
+ 'required' => 'required',
763
+ 'min' => true,
764
+ 'max' => true,
765
+ 'maxlength' => true,
766
+ 'size' => true,
767
+ 'placeholder' => true,
768
+ 'autocomplete' => true,
769
+ 'autocapitalize' => true,
770
+ 'autocorrect' => true,
771
+ 'tabindex' => true,
772
+ 'role' => true,
773
+ 'aria-*' => true,
774
+ 'data-*' => true,
775
+ ),
776
+ 'label' => array(
777
+ 'class' => true,
778
+ 'name' => true,
779
+ 'type' => true,
780
+ 'value' => true,
781
+ 'id' => true,
782
+ 'for' => true,
783
+ 'style' => true,
784
+ ),
785
+ 'form' => array(
786
+ 'class' => true,
787
+ 'name' => true,
788
+ 'value' => true,
789
+ 'id' => true,
790
+ 'style' => true,
791
+ 'action' => true,
792
+ 'method' => true,
793
+ ),
794
+ 'svg' => array(
795
+ 'width' => true,
796
+ 'height' => true,
797
+ 'viewbox' => true,
798
+ 'xmlns' => true,
799
+ 'class' => true,
800
+ 'stroke-*' => true,
801
+ 'fill' => true,
802
+ 'stroke' => true,
803
+ ),
804
+ 'path' => array(
805
+ 'd' => true,
806
+ 'fill' => true,
807
+ 'class' => true,
808
+ 'fill-*' => true,
809
+ 'clip-*' => true,
810
+ 'stroke-linecap' => true,
811
+ 'stroke-linejoin' => true,
812
+ 'stroke-width' => true,
813
+ 'fill-rule' => true,
814
+ ),
815
+
816
+ 'main' => array(
817
+ 'align' => true,
818
+ 'dir' => true,
819
+ 'lang' => true,
820
+ 'xml:lang' => true,
821
+ 'aria-*' => true,
822
+ 'class' => true,
823
+ 'id' => true,
824
+ 'style' => true,
825
+ 'title' => true,
826
+ 'role' => true,
827
+ 'data-*' => true,
828
+ ),
829
+ 'textarea' => array(
830
+ 'autocomplete' => true,
831
+ ),
832
+ 'style' => array(),
833
+ 'link' => array(
834
+ 'rel' => true,
835
+ 'id' => true,
836
+ 'href' => true,
837
+ 'media' => true,
838
+ ),
839
+ 'a' => array(
840
+ 'x-on:click' => true,
841
+ ),
842
+ 'polygon' => array(
843
+ 'class' => true,
844
+ 'points' => true,
845
+ ),
846
+ );
847
 
848
  $allowedtags = array_merge_recursive( $context_allowed_tags, $custom_allowed_tags );
849
 
856
  * Allow CSS style in WP Kses
857
  *
858
  * @since 4.5.4
859
+ *
860
  * @since 4.7.3 Returns empty array to whitelist all CSS properties.
861
  */
862
  function ig_es_allowed_css_style( $default_allowed_attr ) {
865
  }
866
 
867
  if ( ! function_exists( 'ig_es_increase_memory_limit' ) ) {
868
+
869
  /**
870
  * Return memory limit required for ES heavy operations
871
  *
880
  }
881
 
882
  if ( ! function_exists( 'ig_es_remove_utf8_bom' ) ) {
883
+
884
  /**
885
  * Remove UTF-8 BOM signature.
886
  *
887
  * @param string $string String to handle.
888
  *
889
  * @return string
890
+ *
891
  * @since 4.5.4
892
  */
893
  function ig_es_remove_utf8_bom( $string = '' ) {
903
  }
904
 
905
  if ( ! function_exists( 'ig_es_covert_to_utf8_encoding' ) ) {
906
+
907
  /**
908
  * Function to convert existing string to its UTF-8 equivalent string.
909
  *
910
  * @param string $data String to handle.
911
+ * @param bool $use_mb Flag to determine whether we should use mb_* functions while detecting and converting the encoding.
912
  *
913
  * @return string $data
914
+ *
915
  * @since 4.5.6
916
  */
917
  function ig_es_covert_to_utf8_encoding( $data = '', $use_mb = false ) {
918
+
919
  // Check if we can use mb_* functions.
920
  if ( $use_mb ) {
921
  // Detect character encoding. detecting order is 1.UTF-8 2. ISO-8859-1.
939
  if ( ! function_exists( 'ig_es_insert_widget_in_sidebar' ) ) {
940
  /**
941
  * Insert a widget in a sidebar.
942
+ *
943
  * @param string $widget_id ID of the widget (search, recent-posts, etc.)
944
+ * @param array $widget_data Widget settings.
945
  * @param string $sidebar ID of the sidebar.
946
  * @param string $allow_duplicate Flag to check whether we should add widget even if added to the sidebar already.
947
+ *
948
  * @return boolean
949
+ *
950
  * @since 4.6.0
951
  */
952
  function ig_es_insert_widget_in_sidebar( $widget_id, $widget_data, $sidebar, $allow_duplicate = false ) {
976
  // Add new widget only if it already not added in the sidebar or duplicate widget is allowed.
977
  if ( ! $widget_already_added || $allow_duplicate ) {
978
  $next_key = $numeric_keys ? max( $numeric_keys ) + 1 : 1;
979
+
980
  // Add this widget to the sidebar
981
  $sidebars_widgets[ $sidebar ][] = $widget_id . '-' . $next_key;
982
+
983
  // Add the new widget instance
984
  $widget_instances[ $next_key ] = $widget_data;
985
+
986
  // Store updated sidebars, widgets and their instances
987
  update_option( 'sidebars_widgets', $sidebars_widgets );
988
  update_option( 'widget_' . $widget_id, $widget_instances );
989
 
990
  return true;
991
  }
992
+
993
  return false;
994
  }
995
  }
lite/includes/feedback.php CHANGED
@@ -2,7 +2,6 @@
2
 
3
  /**
4
  * Get additional system & plugin specific information for feedback
5
- *
6
  */
7
  if ( ! function_exists( 'ig_es_get_additional_info' ) ) {
8
 
@@ -55,7 +54,7 @@ function ig_es_render_general_feedback_widget() {
55
  'force' => true,
56
  'confirmButtonText' => __( 'Send', 'email-subscribers' ),
57
  'consent_text' => __( 'Allow Email Subscribers to track plugin usage. It will help us to understand your issue better. We guarantee no sensitive data is collected.', 'email-subscribers' ),
58
- 'name' => ''
59
  );
60
 
61
  ES_Common::render_feedback_widget( $params );
@@ -80,13 +79,13 @@ function ig_es_render_broadcast_created_feedback_widget() {
80
  'position' => 'top-end',
81
  'width' => 300,
82
  'delay' => 2, // seconds
83
- 'confirmButtonText' => __( 'Send', 'email-subscribers' )
84
  );
85
 
86
  ES_Common::render_feedback_widget( $params );
87
  }
88
 
89
- //add_action( 'ig_es_broadcast_created', 'ig_es_render_broadcast_created_feedback_widget' );
90
 
91
  /**
92
  * Render Broadcast Created feedback widget.
@@ -123,7 +122,7 @@ function ig_es_render_fb_widget() {
123
  'delay' => 2, // seconds
124
  'confirmButtonText' => '<i class="dashicons dashicons-es dashicons-facebook"></i> ' . __( 'Join Now', 'email-subscribers' ),
125
  'confirmButtonLink' => 'https://www.facebook.com/groups/2298909487017349/',
126
- 'show_once' => true
127
  );
128
 
129
  ES_Common::render_feedback_widget( $params );
@@ -228,20 +227,25 @@ function ig_es_render_iges_merge_feedback() {
228
  'event' => $event,
229
  'desc' => '<div><p class="mt-4">You use <a href="https://wordpress.org/plugins/email-subscribers" target="_blank"><b class="text-blue-700 font-semibold underline">Email Subscribers</b></a> to send email campaigns.</p><p class="mt-3">Would you like us to include onsite popups and action bars in the plugin as well? This way you can <b class="font-semibold">convert visitors to subscribers, drive traffic and run email marketing from a single plugin</b>.</p> <p class="mt-3">Why do we ask?</p> <p class="mt-3">Our <a class="text-blue-700 font-semibold underline" href="https://wordpress.org/plugins/icegram" target="_blank"><b>Icegram</b></a> plugin already does onsite campaigns. We are thinking of merging Icegram & Email Subscribers into a single plugin.</p> <p class="mt-3"><b class="font-semibold">Will a comprehensive ConvertKit / MailChimp like email + onsite campaign plugin be useful to you?</b></p> </div><p class="mt-3">',
230
  'poll_options' => array(
231
- 'yes' => array( 'text' => '<b>' . __( 'Yes', 'email-subscribers' ) . '</b>', 'color' => 'green' ),
232
- 'no' => array( 'text' => '<b>' . __( 'No', 'email-subscribers' ) . '</b>', 'color' => 'red' )
 
 
 
 
 
 
233
  ),
234
  'allow_multiple' => false,
235
  'position' => 'bottom-center',
236
  'width' => 400,
237
  'delay' => 2, // seconds
238
  'confirmButtonText' => __( 'Send my feedback to <b>Icegram team</b>', 'email-subscribers' ),
239
- 'show_once' => true
240
  );
241
 
242
  ES_Common::render_feedback_widget( $params );
243
  }
244
-
245
  }
246
  }
247
 
@@ -321,14 +325,13 @@ if ( ! function_exists( 'ig_es_show_plugin_usage_tracking_notice' ) ) {
321
  */
322
  function ig_es_show_plugin_usage_tracking_notice( $enable ) {
323
 
324
-
325
  // Show notice ES pages except the dashboard page.
326
  if ( ES()->is_es_admin_screen() ) {
327
 
328
  $current_page = ig_es_get_request_data( 'page' );
329
 
330
  if ( 'es_dashboard' !== $current_page ) {
331
-
332
  $enable = true;
333
  }
334
  }
2
 
3
  /**
4
  * Get additional system & plugin specific information for feedback
 
5
  */
6
  if ( ! function_exists( 'ig_es_get_additional_info' ) ) {
7
 
54
  'force' => true,
55
  'confirmButtonText' => __( 'Send', 'email-subscribers' ),
56
  'consent_text' => __( 'Allow Email Subscribers to track plugin usage. It will help us to understand your issue better. We guarantee no sensitive data is collected.', 'email-subscribers' ),
57
+ 'name' => '',
58
  );
59
 
60
  ES_Common::render_feedback_widget( $params );
79
  'position' => 'top-end',
80
  'width' => 300,
81
  'delay' => 2, // seconds
82
+ 'confirmButtonText' => __( 'Send', 'email-subscribers' ),
83
  );
84
 
85
  ES_Common::render_feedback_widget( $params );
86
  }
87
 
88
+ // add_action( 'ig_es_broadcast_created', 'ig_es_render_broadcast_created_feedback_widget' );
89
 
90
  /**
91
  * Render Broadcast Created feedback widget.
122
  'delay' => 2, // seconds
123
  'confirmButtonText' => '<i class="dashicons dashicons-es dashicons-facebook"></i> ' . __( 'Join Now', 'email-subscribers' ),
124
  'confirmButtonLink' => 'https://www.facebook.com/groups/2298909487017349/',
125
+ 'show_once' => true,
126
  );
127
 
128
  ES_Common::render_feedback_widget( $params );
227
  'event' => $event,
228
  'desc' => '<div><p class="mt-4">You use <a href="https://wordpress.org/plugins/email-subscribers" target="_blank"><b class="text-blue-700 font-semibold underline">Email Subscribers</b></a> to send email campaigns.</p><p class="mt-3">Would you like us to include onsite popups and action bars in the plugin as well? This way you can <b class="font-semibold">convert visitors to subscribers, drive traffic and run email marketing from a single plugin</b>.</p> <p class="mt-3">Why do we ask?</p> <p class="mt-3">Our <a class="text-blue-700 font-semibold underline" href="https://wordpress.org/plugins/icegram" target="_blank"><b>Icegram</b></a> plugin already does onsite campaigns. We are thinking of merging Icegram & Email Subscribers into a single plugin.</p> <p class="mt-3"><b class="font-semibold">Will a comprehensive ConvertKit / MailChimp like email + onsite campaign plugin be useful to you?</b></p> </div><p class="mt-3">',
229
  'poll_options' => array(
230
+ 'yes' => array(
231
+ 'text' => '<b>' . __( 'Yes', 'email-subscribers' ) . '</b>',
232
+ 'color' => 'green',
233
+ ),
234
+ 'no' => array(
235
+ 'text' => '<b>' . __( 'No', 'email-subscribers' ) . '</b>',
236
+ 'color' => 'red',
237
+ ),
238
  ),
239
  'allow_multiple' => false,
240
  'position' => 'bottom-center',
241
  'width' => 400,
242
  'delay' => 2, // seconds
243
  'confirmButtonText' => __( 'Send my feedback to <b>Icegram team</b>', 'email-subscribers' ),
244
+ 'show_once' => true,
245
  );
246
 
247
  ES_Common::render_feedback_widget( $params );
248
  }
 
249
  }
250
  }
251
 
325
  */
326
  function ig_es_show_plugin_usage_tracking_notice( $enable ) {
327
 
 
328
  // Show notice ES pages except the dashboard page.
329
  if ( ES()->is_es_admin_screen() ) {
330
 
331
  $current_page = ig_es_get_request_data( 'page' );
332
 
333
  if ( 'es_dashboard' !== $current_page ) {
334
+
335
  $enable = true;
336
  }
337
  }
lite/includes/feedback/class-ig-feedback.php CHANGED
@@ -24,7 +24,6 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
24
  *
25
  * @since 1.0.13
26
  * @var string
27
- *
28
  */
29
  public $version = '1.2.5';
30
  /**
@@ -69,6 +68,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
69
 
70
  /**
71
  * Enable/Disable Dev Mode
 
72
  * @var bool
73
  */
74
  public $is_dev_mode = true;
@@ -192,10 +192,10 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
192
 
193
  if ( $can_ask_user_for_review ) {
194
 
195
- $current_page_url = "//" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
196
 
197
  $got_feedback = false;
198
- /************** Update Review Status ********************/
199
  $nonce = ! empty( $_GET['ig_feedback_nonce'] ) ? esc_attr( wp_unslash( $_GET['ig_feedback_nonce'] ) ) : '';
200
  $nonce_verified = wp_verify_nonce( $nonce, 'review' );
201
 
@@ -205,7 +205,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
205
 
206
  if ( ! empty( $action ) && $this->is_valid_action( $action ) ) {
207
  update_user_meta( $current_user_id, $action, 1 );
208
- update_user_meta( $current_user_id, $action . "_time", time() );
209
 
210
  // Got the review request?
211
  // Redirect them to review page
@@ -216,7 +216,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
216
  if ( ! empty( $url ) ) {
217
  ?>
218
 
219
- <meta http-equiv="refresh" content="0; url=<?php echo $url; ?>"/>
220
 
221
  <?php
222
  }
@@ -225,7 +225,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
225
 
226
  $got_feedback = true;
227
  }
228
- /************** Update Review Status (End) ********************/
229
 
230
  if ( ! $got_feedback ) {
231
 
@@ -236,7 +236,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
236
  $message_data = array(
237
  'review_url' => $review_url,
238
  'icon_url' => $icon_url,
239
- 'message' => $message
240
  );
241
 
242
  $message_data = apply_filters( $this->plugin_abbr . '_review_message_data', $message_data );
@@ -254,32 +254,32 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
254
 
255
  ?>
256
 
257
- <style type="text/css">
258
 
259
- .ig-feedback-notice-links li {
260
- display: inline-block;
261
- margin-right: 15px;
262
- }
263
 
264
- .ig-feedback-notice-links li a {
265
- display: inline-block;
266
- color: #10738b;
267
- text-decoration: none;
268
- padding-left: 26px;
269
- position: relative;
270
- }
271
 
272
- .ig-feedback-notice {
273
- display: flex;
274
- align-items: center;
275
- }
276
 
277
- .ig-feedback-plugin-icon {
278
- float: left;
279
- margin-right: 0.5em;
280
- }
281
 
282
- </style>
283
 
284
  <?php
285
 
@@ -287,10 +287,17 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
287
  echo '<span class="ig-feedback-plugin-icon"> <img src="' . $icon_url . '" alt="Logo"/></span>';
288
  echo $message;
289
  echo "<ul class='ig-feedback-notice-links'>";
290
- echo sprintf( '<li><a href="%s" class="button-primary" target="_blank" data-rated="' . esc_attr__( "Thank You :) ",
291
- $this->plugin ) . '"><span class="dashicons dashicons-external"></span>&nbsp;&nbsp;Ok, you deserve it</a></li> <li><a href="%s"><span class="dashicons dashicons-calendar-alt"></span>&nbsp;&nbsp;Maybe later</a></li><li><a href="%s"><span class="dashicons dashicons-smiley"></span>&nbsp;&nbsp;I already did!</a></li><li><a href="%s"><span class="dashicons dashicons-no"></span>&nbsp;&nbsp;Don\'t ask me again</a></li>',
292
- esc_url( $review_url ), esc_url( $maybe_later_url ), esc_url( $already_did_url ), esc_url( $no_bug_url ) );
293
- echo "</ul></span>";
 
 
 
 
 
 
 
294
  echo '</div>';
295
  }
296
  }
@@ -403,7 +410,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
403
  'consent_text' => 'You are agree to our terms and condition',
404
  'email' => $this->get_contact_email(),
405
  'name' => '',
406
- 'consent' => false
407
  );
408
 
409
  $params = wp_parse_args( $params, $default_params );
@@ -429,7 +436,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
429
 
430
  ?>
431
 
432
- <script>
433
 
434
  function doSend(rating, details) {
435
 
@@ -542,7 +549,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
542
  showWidget(delay);
543
 
544
 
545
- </script>
546
  <?php
547
  }
548
 
@@ -559,14 +566,14 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
559
 
560
  ?>
561
 
562
- <div class="rating">
563
- <!--elements are in reversed order, to allow "previous sibling selectors" in CSS-->
564
- <input class="ratings" type="radio" name="rating" value="5" id="5"><label for="5">☆</label>
565
- <input class="ratings" type="radio" name="rating" value="4" id="4"><label for="4">☆</label>
566
- <input class="ratings" type="radio" name="rating" value="3" id="3"><label for="3">☆</label>
567
- <input class="ratings" type="radio" name="rating" value="2" id="2"><label for="2">☆</label>
568
- <input class="ratings" type="radio" name="rating" value="1" id="1"><label for="1">☆</label>
569
- </div>
570
 
571
  <?php
572
 
@@ -590,15 +597,15 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
590
 
591
  ?>
592
 
593
- <div class="emoji">
594
- <!--elements are in reversed order, to allow "previous sibling selectors" in CSS-->
595
- <input class="emojis" type="radio" name="rating" value="love" id="5"/><label for="5" class="ig-emoji" data-reaction="Love">😍</label>
596
- <input class="emojis" type="radio" name="rating" value="smile" id="4"/><label for="4" class="ig-emoji" data-reaction="Smile">😊</label>
597
- <input class="emojis" type="radio" name="rating" value="neutral" id="3"/><label for="3" class="ig-emoji" data-reaction="Neutral">😐</label>
598
- <input class="emojis" type="radio" name="rating" value="sad" id="1"/><label for="2" class="ig-emoji" data-reaction="Sad">😠</label>
599
- <input class="emojis" type="radio" name="rating" value="angry" id="1"/><label for="1" class="ig-emoji" data-reaction="Angry">😡</label>
600
- </div>
601
- <div id="emoji-info"></div>
602
 
603
  <?php
604
 
@@ -623,27 +630,27 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
623
 
624
  ?>
625
 
626
- <div class="ig-general-feedback" id="ig-general-feedback-<?php echo $this->plugin; ?>">
627
- <form class="ig-general-feedback" id="ig-general-feedback">
628
- <p class="ig-feedback-data-name">
629
- <label class="ig-label">Name</label><br/>
630
- <input type="text" name="feedback_data[name]" id="ig-feedback-data-name" value="<?php echo $params['name']; ?>"/>
631
- </p>
632
- <p class="ig-feedback-data-email">
633
- <label class="ig-label"">Email</label><br/>
634
- <input type="email" name="feedback_data[email]" id="ig-feedback-data-email" value="<?php echo $params['email']; ?>"/>
635
- </p>
636
- <p class="ig-feedback-data-message">
637
- <label class="ig-label"">Feedback</label><br/>
638
- <textarea name="feedback_data[details]" id="ig-feedback-data-message"></textarea>
639
- </p>
640
  <?php if ( isset( $params['consent'] ) && $params['consent'] === true ) { ?>
641
- <p>
642
- <input type="checkbox" name="feedback_data[collect_system_info]" checked="checked" id="ig-feedback-data-consent"/><?php echo $params['consent_text']; ?>
643
- </p>
644
  <?php } ?>
645
- </form>
646
- </div>
647
 
648
  <?php
649
 
@@ -659,7 +666,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
659
  ob_start();
660
  ?>
661
 
662
- <script type="text/javascript">
663
 
664
  jQuery(document).ready(function ($) {
665
 
@@ -782,7 +789,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
782
  });
783
  });
784
 
785
- </script>
786
 
787
 
788
  <?php
@@ -798,19 +805,19 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
798
 
799
  $params = $this->prepare_widget_params( $params );
800
 
801
- $title = $params['title'];
802
- $widget_tyoe = !empty($params['widget_tyoe']) ? $params['widget_tyoe'] : 'question';
803
- $slug = sanitize_title( $title );
804
- $event = $this->event_prefix . $params['event'];
805
- $html = ! empty( $params['html'] ) ? $params['html'] : '';
806
  $confirm_button_link = ! empty( $params['confirmButtonLink'] ) ? $params['confirmButtonLink'] : '';
807
- $cancel_button_link = ! empty( $params['cancelButtonLink'] ) ? $params['cancelButtonLink'] : '';
808
- $show_cancel_button = ! empty( $params['showCancelButton'] ) ? 'true' : 'false';
809
- $cancel_button_text = ! empty( $params['cancelButtonText'] ) ? $params['cancelButtonText'] : 'Cancel';
810
 
811
  ?>
812
 
813
- <script>
814
 
815
  Swal.mixin({
816
  type: '<?php echo $widget_tyoe; ?>',
@@ -862,10 +869,10 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
862
  '<?php echo $cancel_button_link; ?>',
863
  '_blank' // <- This is what makes it open in a new window.
864
  );
865
- }
866
  });
867
 
868
- </script>
869
 
870
  <?php
871
  }
@@ -897,20 +904,20 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
897
 
898
  ?>
899
 
900
- <div class="ig-general-feedback" id="ig-general-feedback-<?php echo $this->plugin; ?>">
901
- <form class="ig-general-feedback" id="ig-general-feedback">
902
- <p><?php echo $desc; ?></p>
903
 
904
- <p class="ig-general-feedback mb-3">
905
  <?php foreach ( $poll_options as $value => $option ) { ?>
906
- <input type="radio" name="feedback_data[poll_options]" value="<?php echo $value; ?>"><b style="color: <?php echo $option['color']; ?>"><?php echo $option['text']; ?></b><br/>
907
  <?php } ?>
908
- </p>
909
- <p class="ig-feedback-data-poll-message mb-3" id="ig-feedback-data-poll-message">
910
- <textarea name="feedback_data[details]" id="ig-feedback-data-poll-additional-message" placeholder="Additional feedback"></textarea>
911
- </p>
912
- </form>
913
- </div>
914
 
915
  <?php
916
 
@@ -925,7 +932,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
925
 
926
  ?>
927
 
928
- <script type="text/javascript">
929
 
930
  jQuery(document).ready(function ($) {
931
 
@@ -1022,7 +1029,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1022
 
1023
  });
1024
 
1025
- </script>
1026
 
1027
 
1028
  <?php
@@ -1063,7 +1070,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1063
  $event = $this->event_prefix . 'plugin.deactivation';
1064
 
1065
  ?>
1066
- <script type="text/javascript">
1067
  jQuery(function ($) {
1068
  var $deactivateLink = $('#the-list').find('[data-slug="<?php echo $this->plugin; ?>"] span.deactivate a'),
1069
  $overlay = $('#ig-deactivate-survey-<?php echo $this->plugin; ?>'),
@@ -1208,7 +1215,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1208
  }
1209
  });
1210
  });
1211
- </script>
1212
  <?php
1213
  }
1214
 
@@ -1223,108 +1230,108 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1223
  return;
1224
  }
1225
  ?>
1226
- <style type="text/css">
1227
- .ig-deactivate-survey-modal {
1228
- display: none;
1229
- table-layout: fixed;
1230
- position: fixed;
1231
- z-index: 9999;
1232
- width: 100%;
1233
- height: 100%;
1234
- text-align: center;
1235
- font-size: 14px;
1236
- top: 0;
1237
- left: 0;
1238
- background: rgba(0, 0, 0, 0.8);
1239
- }
1240
-
1241
- .ig-deactivate-survey-wrap {
1242
- display: table-cell;
1243
- vertical-align: middle;
1244
- }
1245
-
1246
- .ig-deactivate-survey {
1247
- background-color: #fff;
1248
- max-width: 550px;
1249
- margin: 0 auto;
1250
- padding: 30px;
1251
- text-align: left;
1252
- }
1253
-
1254
- .ig-deactivate-survey .error {
1255
- display: block;
1256
- color: red;
1257
- margin: 0 0 10px 0;
1258
- }
1259
-
1260
- .ig-deactivate-survey-title {
1261
- display: block;
1262
- font-size: 18px;
1263
- font-weight: 700;
1264
- text-transform: uppercase;
1265
- border-bottom: 1px solid #ddd;
1266
- padding: 0 0 18px 0;
1267
- margin: 0 0 18px 0;
1268
- }
1269
-
1270
- .ig-deactivate-survey-options {
1271
- border-bottom: 1px solid #ddd;
1272
- padding: 0 0 18px 0;
1273
- margin: 0 0 18px 0;
1274
- }
1275
-
1276
- .ig-deactivate-survey-info-data {
1277
- padding: 0 0 18px 0;
1278
- margin: 10px 10px 10px 30px;
1279
- }
1280
-
1281
- .ig-deactivate-survey-info-name, .ig-deactivate-survey-info-email-address {
1282
- width: 230px;
1283
- margin: 10px;
1284
- }
1285
-
1286
- .ig-deactivate-survey-title span {
1287
- color: #999;
1288
- margin-right: 10px;
1289
- }
1290
-
1291
- .ig-deactivate-survey-desc {
1292
- display: block;
1293
- font-weight: 600;
1294
- margin: 0 0 18px 0;
1295
- }
1296
-
1297
- .ig-deactivate-survey-option {
1298
- margin: 0 0 10px 0;
1299
- }
1300
-
1301
- .ig-deactivate-survey-option-input {
1302
- margin-right: 10px !important;
1303
- }
1304
-
1305
- .ig-deactivate-survey-option-details {
1306
- display: none;
1307
- width: 90%;
1308
- margin: 10px 0 0 30px;
1309
- }
1310
-
1311
- .ig-deactivate-survey-footer {
1312
- margin-top: 18px;
1313
- }
1314
-
1315
- .ig-deactivate-survey-deactivate {
1316
- float: right;
1317
- font-size: 13px;
1318
- color: #ccc;
1319
- text-decoration: none;
1320
- padding-top: 7px;
1321
- }
1322
-
1323
- .ig-deactivate-survey-loader {
1324
- vertical-align: middle;
1325
- padding: 10px;
1326
- }
1327
- </style>
1328
  <?php
1329
  }
1330
 
@@ -1344,7 +1351,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1344
  $options = array(
1345
  1 => array(
1346
  'title' => esc_html__( 'I no longer need the plugin', $this->plugin ),
1347
- 'slug' => 'i-no-longer-need-the-plugin'
1348
  ),
1349
  2 => array(
1350
  'title' => esc_html__( 'I\'m switching to a different plugin', $this->plugin ),
@@ -1353,11 +1360,11 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1353
  ),
1354
  3 => array(
1355
  'title' => esc_html__( 'I couldn\'t get the plugin to work', $this->plugin ),
1356
- 'slug' => 'i-could-not-get-the-plugin-to-work'
1357
  ),
1358
  4 => array(
1359
  'title' => esc_html__( 'It\'s a temporary deactivation', $this->plugin ),
1360
- 'slug' => 'it-is-a-temporary-deactivation'
1361
  ),
1362
  5 => array(
1363
  'title' => esc_html__( 'Other', $this->plugin ),
@@ -1366,40 +1373,40 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1366
  ),
1367
  );
1368
  ?>
1369
- <div class="ig-deactivate-survey-modal" id="ig-deactivate-survey-<?php echo $this->plugin; ?>">
1370
- <div class="ig-deactivate-survey-wrap">
1371
- <form class="ig-deactivate-survey" method="post">
1372
- <span class="ig-deactivate-survey-title"><span class="dashicons dashicons-testimonial"></span><?php echo ' ' . esc_html__( 'Quick Feedback', $this->plugin ); ?></span>
1373
- <span class="ig-deactivate-survey-desc"><?php echo sprintf( esc_html__( 'If you have a moment, please share why you are deactivating %s:', $this->plugin ), $this->name ); ?></span>
1374
- <div class="ig-deactivate-survey-options">
1375
  <?php foreach ( $options as $id => $option ) : ?>
1376
- <div class="ig-deactivate-survey-option">
1377
- <label for="ig-deactivate-survey-option-<?php echo $this->plugin; ?>-<?php echo $id; ?>" class="ig-deactivate-survey-option-label">
1378
- <input id="ig-deactivate-survey-option-<?php echo $this->plugin; ?>-<?php echo $id; ?>" class="ig-deactivate-survey-option-input" type="radio" name="code" value="<?php echo $id; ?>" data-option-slug="<?php echo $option['slug']; ?>"/>
1379
- <span class="ig-deactivate-survey-option-reason"><?php echo $option['title']; ?></span>
1380
- </label>
1381
  <?php if ( ! empty( $option['details'] ) ) : ?>
1382
- <input class="ig-deactivate-survey-option-details" type="text" placeholder="<?php echo $option['details']; ?>"/>
1383
  <?php endif; ?>
1384
- </div>
1385
  <?php endforeach; ?>
1386
- </div>
1387
- <div class="ig-deactivate-survey-help-consent">
1388
- <input id="ig-deactivate-survey-help-consent-<?php echo $this->plugin; ?>" class="ig-deactivate-survey-option-input" type="checkbox" name="code" data-option-slug="<?php echo $option['slug']; ?>"/><b>Yes, I give my consent to track plugin usage and contact me back to make this plugin works!</b>
1389
- </div>
1390
- <div class="ig-deactivate-survey-info-data">
1391
-
1392
- <input type="text" class="ig-deactivate-survey-info-name" id="ig-deactivate-survey-info-name" placeholder="Enter Name" name="ig-deactivate-survey-info-name" value=""/>
1393
- <input type="text" class="ig-deactivate-survey-info-email-address" id="ig-deactivate-survey-info-email-address" name="ig-deactivate-survey-info-email-address" value="<?php echo $email; ?>"/>
1394
- </div>
1395
- <div class="ig-deactivate-survey-footer">
1396
- <button type="submit" class="ig-deactivate-survey-submit button button-primary button-large"><?php echo sprintf( esc_html__( 'Submit %s Deactivate', $this->plugin ), '&amp;' ); ?></button>
1397
- <img class="ig-deactivate-survey-loader" id="ig-deactivate-survey-loader" src="<?php echo plugin_dir_url( __FILE__ ); ?>/assets/images/loading.gif"/>
1398
- <a href="#" class="ig-deactivate-survey-deactivate"><?php echo sprintf( esc_html__( 'Skip %s Deactivate', $this->plugin ), '&amp;' ); ?></a>
1399
- </div>
1400
- </form>
1401
- </div>
1402
- </div>
1403
  <?php
1404
  }
1405
 
@@ -1483,7 +1490,6 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1483
  $is_local_url = true;
1484
  continue;
1485
  }
1486
-
1487
  }
1488
  if ( substr_count( $host, '.' ) > 1 ) {
1489
  $subdomains_to_check = array( 'dev.', '*.staging.', 'beta.', 'test.' );
@@ -1584,7 +1590,6 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1584
  return true;
1585
  }
1586
  }
1587
-
1588
  }
1589
 
1590
  return false;
@@ -1595,7 +1600,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1595
  * Set event into transient
1596
  *
1597
  * @param $event
1598
- * @param int $expiry in days
1599
  */
1600
  public function set_event_transient( $event, $expiry = 45 ) {
1601
  set_transient( $event, 1, time() + ( 86400 * $expiry ) );
@@ -1665,7 +1670,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1665
  'plugin' => sanitize_key( $plugin ),
1666
  'locale' => get_locale(),
1667
  'wp_version' => get_bloginfo( 'version' ),
1668
- 'php_version' => PHP_VERSION
1669
  );
1670
 
1671
  $meta_info = wp_parse_args( $meta_info, $default_meta_info );
@@ -1685,7 +1690,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1685
  'timeout' => 15,
1686
  'sslverify' => false,
1687
  'body' => $data,
1688
- 'blocking' => false
1689
  );
1690
 
1691
  $this->set_feedback_data( $plugin_abbr, $data['event'], $data['feedback'] );
@@ -1695,7 +1700,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1695
  $this->set_event_transient( $data['event'] );
1696
  }
1697
 
1698
- $response = wp_remote_post( $this->get_api_url( $is_dev_mode ), $args );
1699
  $result['status'] = 'success';
1700
  if ( $response instanceof WP_Error ) {
1701
  $error_message = $response->get_error_message();
@@ -1706,4 +1711,4 @@ if ( ! class_exists( 'IG_Feedback_V_1_2_5' ) ) {
1706
  die( json_encode( $result ) );
1707
  }
1708
  }
1709
- } // End if().
24
  *
25
  * @since 1.0.13
26
  * @var string
 
27
  */
28
  public $version = '1.2.5';
29
  /**
68
 
69
  /**
70
  * Enable/Disable Dev Mode
71
+ *
72
  * @var bool
73
  */
74
  public $is_dev_mode = true;
192
 
193
  if ( $can_ask_user_for_review ) {
194
 
195
+ $current_page_url = '//' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
196
 
197
  $got_feedback = false;
198
+ /************** Update Review Status */
199
  $nonce = ! empty( $_GET['ig_feedback_nonce'] ) ? esc_attr( wp_unslash( $_GET['ig_feedback_nonce'] ) ) : '';
200
  $nonce_verified = wp_verify_nonce( $nonce, 'review' );
201
 
205
 
206
  if ( ! empty( $action ) && $this->is_valid_action( $action ) ) {
207
  update_user_meta( $current_user_id, $action, 1 );
208
+ update_user_meta( $current_user_id, $action . '_time', time() );
209
 
210
  // Got the review request?
211
  // Redirect them to review page
216
  if ( ! empty( $url ) ) {
217
  ?>
218
 
219
+ <meta http-equiv="refresh" content="0; url=<?php echo $url; ?>"/>
220
 
221
  <?php
222
  }
225
 
226
  $got_feedback = true;
227
  }
228
+ /************** Update Review Status (End) */
229
 
230
  if ( ! $got_feedback ) {
231
 
236
  $message_data = array(
237
  'review_url' => $review_url,
238
  'icon_url' => $icon_url,
239
+ 'message' => $message,
240
  );
241
 
242
  $message_data = apply_filters( $this->plugin_abbr . '_review_message_data', $message_data );
254
 
255
  ?>
256
 
257
+ <style type="text/css">
258
 
259
+ .ig-feedback-notice-links li {
260
+ display: inline-block;
261
+ margin-right: 15px;
262
+ }
263
 
264
+ .ig-feedback-notice-links li a {
265
+ display: inline-block;
266
+ color: #10738b;
267
+ text-decoration: none;
268
+ padding-left: 26px;
269
+ position: relative;
270
+ }
271
 
272
+ .ig-feedback-notice {
273
+ display: flex;
274
+ align-items: center;
275
+ }
276
 
277
+ .ig-feedback-plugin-icon {
278
+ float: left;
279
+ margin-right: 0.5em;
280
+ }
281
 
282
+ </style>
283
 
284
  <?php
285
 
287
  echo '<span class="ig-feedback-plugin-icon"> <img src="' . $icon_url . '" alt="Logo"/></span>';
288
  echo $message;
289
  echo "<ul class='ig-feedback-notice-links'>";
290
+ echo sprintf(
291
+ '<li><a href="%s" class="button-primary" target="_blank" data-rated="' . esc_attr__(
292
+ 'Thank You :) ',
293
+ $this->plugin
294
+ ) . '"><span class="dashicons dashicons-external"></span>&nbsp;&nbsp;Ok, you deserve it</a></li> <li><a href="%s"><span class="dashicons dashicons-calendar-alt"></span>&nbsp;&nbsp;Maybe later</a></li><li><a href="%s"><span class="dashicons dashicons-smiley"></span>&nbsp;&nbsp;I already did!</a></li><li><a href="%s"><span class="dashicons dashicons-no"></span>&nbsp;&nbsp;Don\'t ask me again</a></li>',
295
+ esc_url( $review_url ),
296
+ esc_url( $maybe_later_url ),
297
+ esc_url( $already_did_url ),
298
+ esc_url( $no_bug_url )
299
+ );
300
+ echo '</ul></span>';
301
  echo '</div>';
302
  }
303
  }
410
  'consent_text' => 'You are agree to our terms and condition',
411
  'email' => $this->get_contact_email(),
412
  'name' => '',
413
+ 'consent' => false,
414
  );
415
 
416
  $params = wp_parse_args( $params, $default_params );
436
 
437
  ?>
438
 
439
+ <script>
440
 
441
  function doSend(rating, details) {
442
 
549
  showWidget(delay);
550
 
551
 
552
+ </script>
553
  <?php
554
  }
555
 
566
 
567
  ?>
568
 
569
+ <div class="rating">
570
+ <!--elements are in reversed order, to allow "previous sibling selectors" in CSS-->
571
+ <input class="ratings" type="radio" name="rating" value="5" id="5"><label for="5">☆</label>
572
+ <input class="ratings" type="radio" name="rating" value="4" id="4"><label for="4">☆</label>
573
+ <input class="ratings" type="radio" name="rating" value="3" id="3"><label for="3">☆</label>
574
+ <input class="ratings" type="radio" name="rating" value="2" id="2"><label for="2">☆</label>
575
+ <input class="ratings" type="radio" name="rating" value="1" id="1"><label for="1">☆</label>
576
+ </div>
577
 
578
  <?php
579
 
597
 
598
  ?>
599
 
600
+ <div class="emoji">
601
+ <!--elements are in reversed order, to allow "previous sibling selectors" in CSS-->
602
+ <input class="emojis" type="radio" name="rating" value="love" id="5"/><label for="5" class="ig-emoji" data-reaction="Love">😍</label>
603
+ <input class="emojis" type="radio" name="rating" value="smile" id="4"/><label for="4" class="ig-emoji" data-reaction="Smile">😊</label>
604
+ <input class="emojis" type="radio" name="rating" value="neutral" id="3"/><label for="3" class="ig-emoji" data-reaction="Neutral">😐</label>
605
+ <input class="emojis" type="radio" name="rating" value="sad" id="1"/><label for="2" class="ig-emoji" data-reaction="Sad">😠</label>
606
+ <input class="emojis" type="radio" name="rating" value="angry" id="1"/><label for="1" class="ig-emoji" data-reaction="Angry">😡</label>
607
+ </div>
608
+ <div id="emoji-info"></div>
609
 
610
  <?php
611
 
630
 
631
  ?>
632
 
633
+ <div class="ig-general-feedback" id="ig-general-feedback-<?php echo $this->plugin; ?>">
634
+ <form class="ig-general-feedback" id="ig-general-feedback">
635
+ <p class="ig-feedback-data-name">
636
+ <label class="ig-label">Name</label><br/>
637
+ <input type="text" name="feedback_data[name]" id="ig-feedback-data-name" value="<?php echo $params['name']; ?>"/>
638
+ </p>
639
+ <p class="ig-feedback-data-email">
640
+ <label class="ig-label"">Email</label><br/>
641
+ <input type="email" name="feedback_data[email]" id="ig-feedback-data-email" value="<?php echo $params['email']; ?>"/>
642
+ </p>
643
+ <p class="ig-feedback-data-message">
644
+ <label class="ig-label"">Feedback</label><br/>
645
+ <textarea name="feedback_data[details]" id="ig-feedback-data-message"></textarea>
646
+ </p>
647
  <?php if ( isset( $params['consent'] ) && $params['consent'] === true ) { ?>
648
+ <p>
649
+ <input type="checkbox" name="feedback_data[collect_system_info]" checked="checked" id="ig-feedback-data-consent"/><?php echo $params['consent_text']; ?>
650
+ </p>
651
  <?php } ?>
652
+ </form>
653
+ </div>
654
 
655
  <?php
656
 
666
  ob_start();
667
  ?>
668
 
669
+ <script type="text/javascript">
670
 
671
  jQuery(document).ready(function ($) {
672
 
789
  });
790
  });
791
 
792
+ </script>
793
 
794
 
795
  <?php
805
 
806
  $params = $this->prepare_widget_params( $params );
807
 
808
+ $title = $params['title'];
809
+ $widget_tyoe = ! empty( $params['widget_tyoe'] ) ? $params['widget_tyoe'] : 'question';
810
+ $slug = sanitize_title( $title );
811
+ $event = $this->event_prefix . $params['event'];
812
+ $html = ! empty( $params['html'] ) ? $params['html'] : '';
813
  $confirm_button_link = ! empty( $params['confirmButtonLink'] ) ? $params['confirmButtonLink'] : '';
814
+ $cancel_button_link = ! empty( $params['cancelButtonLink'] ) ? $params['cancelButtonLink'] : '';
815
+ $show_cancel_button = ! empty( $params['showCancelButton'] ) ? 'true' : 'false';
816
+ $cancel_button_text = ! empty( $params['cancelButtonText'] ) ? $params['cancelButtonText'] : 'Cancel';
817
 
818
  ?>
819
 
820
+ <script>
821
 
822
  Swal.mixin({
823
  type: '<?php echo $widget_tyoe; ?>',
869
  '<?php echo $cancel_button_link; ?>',
870
  '_blank' // <- This is what makes it open in a new window.
871
  );
872
+ }
873
  });
874
 
875
+ </script>
876
 
877
  <?php
878
  }
904
 
905
  ?>
906
 
907
+ <div class="ig-general-feedback" id="ig-general-feedback-<?php echo $this->plugin; ?>">
908
+ <form class="ig-general-feedback" id="ig-general-feedback">
909
+ <p><?php echo $desc; ?></p>
910
 
911
+ <p class="ig-general-feedback mb-3">
912
  <?php foreach ( $poll_options as $value => $option ) { ?>
913
+ <input type="radio" name="feedback_data[poll_options]" value="<?php echo $value; ?>"><b style="color: <?php echo $option['color']; ?>"><?php echo $option['text']; ?></b><br/>
914
  <?php } ?>
915
+ </p>
916
+ <p class="ig-feedback-data-poll-message mb-3" id="ig-feedback-data-poll-message">
917
+ <textarea name="feedback_data[details]" id="ig-feedback-data-poll-additional-message" placeholder="Additional feedback"></textarea>
918
+ </p>
919
+ </form>
920
+ </div>
921
 
922
  <?php
923
 
932
 
933
  ?>
934
 
935
+ <script type="text/javascript">
936
 
937
  jQuery(document).ready(function ($) {
938
 
1029
 
1030
  });
1031
 
1032
+ </script>
1033
 
1034
 
1035
  <?php
1070
  $event = $this->event_prefix . 'plugin.deactivation';
1071
 
1072
  ?>
1073
+ <script type="text/javascript">
1074
  jQuery(function ($) {
1075
  var $deactivateLink = $('#the-list').find('[data-slug="<?php echo $this->plugin; ?>"] span.deactivate a'),
1076
  $overlay = $('#ig-deactivate-survey-<?php echo $this->plugin; ?>'),
1215
  }
1216
  });
1217
  });
1218
+ </script>
1219
  <?php
1220
  }
1221
 
1230
  return;
1231
  }
1232
  ?>
1233
+ <style type="text/css">
1234
+ .ig-deactivate-survey-modal {
1235
+ display: none;
1236
+ table-layout: fixed;
1237
+ position: fixed;
1238
+ z-index: 9999;
1239
+ width: 100%;
1240
+ height: 100%;
1241
+ text-align: center;
1242
+ font-size: 14px;
1243
+ top: 0;
1244
+ left: 0;
1245
+ background: rgba(0, 0, 0, 0.8);
1246
+ }
1247
+
1248
+ .ig-deactivate-survey-wrap {
1249
+ display: table-cell;
1250
+ vertical-align: middle;
1251
+ }
1252
+
1253
+ .ig-deactivate-survey {
1254
+ background-color: #fff;
1255
+ max-width: 550px;
1256
+ margin: 0 auto;
1257
+ padding: 30px;
1258
+ text-align: left;
1259
+ }
1260
+
1261
+ .ig-deactivate-survey .error {
1262
+ display: block;
1263
+ color: red;
1264
+ margin: 0 0 10px 0;
1265
+ }
1266
+
1267
+ .ig-deactivate-survey-title {
1268
+ display: block;
1269
+ font-size: 18px;
1270
+ font-weight: 700;
1271
+ text-transform: uppercase;
1272
+ border-bottom: 1px solid #ddd;
1273
+ padding: 0 0 18px 0;
1274
+ margin: 0 0 18px 0;
1275
+ }
1276
+
1277
+ .ig-deactivate-survey-options {
1278
+ border-bottom: 1px solid #ddd;
1279
+ padding: 0 0 18px 0;
1280
+ margin: 0 0 18px 0;
1281
+ }
1282
+
1283
+ .ig-deactivate-survey-info-data {
1284
+ padding: 0 0 18px 0;
1285
+ margin: 10px 10px 10px 30px;
1286
+ }
1287
+
1288
+ .ig-deactivate-survey-info-name, .ig-deactivate-survey-info-email-address {
1289
+ width: 230px;
1290
+ margin: 10px;
1291
+ }
1292
+
1293
+ .ig-deactivate-survey-title span {
1294
+ color: #999;
1295
+ margin-right: 10px;
1296
+ }
1297
+
1298
+ .ig-deactivate-survey-desc {
1299
+ display: block;
1300
+ font-weight: 600;
1301
+ margin: 0 0 18px 0;
1302
+ }
1303
+
1304
+ .ig-deactivate-survey-option {
1305
+ margin: 0 0 10px 0;
1306
+ }
1307
+
1308
+ .ig-deactivate-survey-option-input {
1309
+ margin-right: 10px !important;
1310
+ }
1311
+
1312
+ .ig-deactivate-survey-option-details {
1313
+ display: none;
1314
+ width: 90%;
1315
+ margin: 10px 0 0 30px;
1316
+ }
1317
+
1318
+ .ig-deactivate-survey-footer {
1319
+ margin-top: 18px;
1320
+ }
1321
+
1322
+ .ig-deactivate-survey-deactivate {
1323
+ float: right;
1324
+ font-size: 13px;
1325
+ color: #ccc;
1326
+ text-decoration: none;
1327
+ padding-top: 7px;
1328
+ }
1329
+
1330
+ .ig-deactivate-survey-loader {
1331
+ vertical-align: middle;
1332
+ padding: 10px;
1333
+ }
1334
+ </style>
1335
  <?php
1336
  }
1337
 
1351
  $options = array(
1352
  1 => array(
1353
  'title' => esc_html__( 'I no longer need the plugin', $this->plugin ),
1354
+ 'slug' => 'i-no-longer-need-the-plugin',
1355
  ),
1356
  2 => array(
1357
  'title' => esc_html__( 'I\'m switching to a different plugin', $this->plugin ),
1360
  ),
1361
  3 => array(
1362
  'title' => esc_html__( 'I couldn\'t get the plugin to work', $this->plugin ),
1363
+ 'slug' => 'i-could-not-get-the-plugin-to-work',
1364
  ),
1365
  4 => array(
1366
  'title' => esc_html__( 'It\'s a temporary deactivation', $this->plugin ),
1367
+ 'slug' => 'it-is-a-temporary-deactivation',
1368
  ),
1369
  5 => array(
1370
  'title' => esc_html__( 'Other', $this->plugin ),
1373
  ),
1374
  );
1375
  ?>
1376
+ <div class="ig-deactivate-survey-modal" id="ig-deactivate-survey-<?php echo $this->plugin; ?>">
1377
+ <div class="ig-deactivate-survey-wrap">
1378
+ <form class="ig-deactivate-survey" method="post">
1379
+ <span class="ig-deactivate-survey-title"><span class="dashicons dashicons-testimonial"></span><?php echo ' ' . esc_html__( 'Quick Feedback', $this->plugin ); ?></span>
1380
+ <span class="ig-deactivate-survey-desc"><?php echo sprintf( esc_html__( 'If you have a moment, please share why you are deactivating %s:', $this->plugin ), $this->name ); ?></span>
1381
+ <div class="ig-deactivate-survey-options">
1382
  <?php foreach ( $options as $id => $option ) : ?>
1383
+ <div class="ig-deactivate-survey-option">
1384
+ <label for="ig-deactivate-survey-option-<?php echo $this->plugin; ?>-<?php echo $id; ?>" class="ig-deactivate-survey-option-label">
1385
+ <input id="ig-deactivate-survey-option-<?php echo $this->plugin; ?>-<?php echo $id; ?>" class="ig-deactivate-survey-option-input" type="radio" name="code" value="<?php echo $id; ?>" data-option-slug="<?php echo $option['slug']; ?>"/>
1386
+ <span class="ig-deactivate-survey-option-reason"><?php echo $option['title']; ?></span>
1387
+ </label>
1388
  <?php if ( ! empty( $option['details'] ) ) : ?>
1389
+ <input class="ig-deactivate-survey-option-details" type="text" placeholder="<?php echo $option['details']; ?>"/>
1390
  <?php endif; ?>
1391
+ </div>
1392
  <?php endforeach; ?>
1393
+ </div>
1394
+ <div class="ig-deactivate-survey-help-consent">
1395
+ <input id="ig-deactivate-survey-help-consent-<?php echo $this->plugin; ?>" class="ig-deactivate-survey-option-input" type="checkbox" name="code" data-option-slug="<?php echo $option['slug']; ?>"/><b>Yes, I give my consent to track plugin usage and contact me back to make this plugin works!</b>
1396
+ </div>
1397
+ <div class="ig-deactivate-survey-info-data">
1398
+
1399
+ <input type="text" class="ig-deactivate-survey-info-name" id="ig-deactivate-survey-info-name" placeholder="Enter Name" name="ig-deactivate-survey-info-name" value=""/>
1400
+ <input type="text" class="ig-deactivate-survey-info-email-address" id="ig-deactivate-survey-info-email-address" name="ig-deactivate-survey-info-email-address" value="<?php echo $email; ?>"/>
1401
+ </div>
1402
+ <div class="ig-deactivate-survey-footer">
1403
+ <button type="submit" class="ig-deactivate-survey-submit button button-primary button-large"><?php echo sprintf( esc_html__( 'Submit %s Deactivate', $this->plugin ), '&amp;' ); ?></button>
1404
+ <img class="ig-deactivate-survey-loader" id="ig-deactivate-survey-loader" src="<?php echo plugin_dir_url( __FILE__ ); ?>/assets/images/loading.gif"/>
1405
+ <a href="#" class="ig-deactivate-survey-deactivate"><?php echo sprintf( esc_html__( 'Skip %s Deactivate', $this->plugin ), '&amp;' ); ?></a>
1406
+ </div>
1407
+ </form>
1408
+ </div>
1409
+ </div>
1410
  <?php
1411
  }
1412
 
1490
  $is_local_url = true;
1491
  continue;
1492
  }
 
1493
  }
1494
  if ( substr_count( $host, '.' ) > 1 ) {
1495
  $subdomains_to_check = array( 'dev.', '*.staging.', 'beta.', 'test.' );
1590
  return true;
1591
  }
1592
  }
 
1593
  }
1594
 
1595
  return false;
1600
  * Set event into transient
1601
  *
1602
  * @param $event
1603
+ * @param int $expiry in days
1604
  */
1605
  public function set_event_transient( $event, $expiry = 45 ) {
1606
  set_transient( $event, 1, time() + ( 86400 * $expiry ) );
1670
  'plugin' => sanitize_key( $plugin ),
1671
  'locale' => get_locale(),
1672
  'wp_version' => get_bloginfo( 'version' ),
1673
+ 'php_version' => PHP_VERSION,
1674
  );
1675
 
1676
  $meta_info = wp_parse_args( $meta_info, $default_meta_info );
1690
  'timeout' => 15,
1691
  'sslverify' => false,
1692
  'body' => $data,
1693
+ 'blocking' => false,
1694
  );
1695
 
1696
  $this->set_feedback_data( $plugin_abbr, $data['event'], $data['feedback'] );
1700
  $this->set_event_transient( $data['event'] );
1701
  }
1702
 
1703
+ $response = wp_remote_post( $this->get_api_url( $is_dev_mode ), $args );
1704
  $result['status'] = 'success';
1705
  if ( $response instanceof WP_Error ) {
1706
  $error_message = $response->get_error_message();
1711
  die( json_encode( $result ) );
1712
  }
1713
  }
1714
+ } // End if().
lite/includes/feedback/class-ig-plugin-usage-tracker.php CHANGED
@@ -71,14 +71,14 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
71
 
72
  /**
73
  * IG Tracker class name
74
- *
75
  * @var string
76
  */
77
  public $tracker_class;
78
 
79
  /**
80
  * Is tracking allowed by default
81
- *
82
  * @var bool
83
  */
84
  public $allowed_by_default;
@@ -107,7 +107,7 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
107
  $this->allowed_by_default = $allowed_by_default;
108
 
109
  // Don't run usage tracker on dev environment if not enabled.
110
- if ( $tracker_class::is_dev_environment() && ! $enable_on_dev ) {
111
  return;
112
  }
113
 
@@ -115,7 +115,7 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
115
  register_deactivation_hook( $plugin_file_path, array( $this, 'do_deactivation_cleanup' ) );
116
 
117
  $tracking_option_name = $this->get_tracking_option_name();
118
-
119
  /**
120
  * Tracking consent add/update handler function.
121
  * These action hooks are triggered by WordPress when we add/update tracking consent option in DB.
@@ -134,7 +134,7 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
134
 
135
  /**
136
  * Handles when optin option is added in db
137
- *
138
  * @param string $option_name
139
  * @param string $value
140
  */
@@ -144,7 +144,7 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
144
 
145
  /**
146
  * Handles when optin option is updated in db
147
- *
148
  * @param string $old_value
149
  * @param string $new_value
150
  * @param string $option_name
@@ -155,7 +155,7 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
155
 
156
  /**
157
  * Common method to handle optin option add/update
158
- *
159
  * @param string $value
160
  */
161
  public function handle_optin_change( $opted_in ) {
@@ -184,13 +184,13 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
184
  * Do deactivation cleanup
185
  */
186
  public function do_deactivation_cleanup() {
187
-
188
  $this->clear_scheduled_cron();
189
 
190
  $survey_status = ig_es_get_request_data( 'survey_status', '' );
191
  if ( ! empty( $survey_status ) && 'skipped' === $survey_status ) {
192
  $extra_params = array(
193
- 'is_deactivated' => 1
194
  );
195
  $this->send_tracking_data( true, $extra_params );
196
  }
@@ -199,13 +199,13 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
199
  /**
200
  * Add weekly cron schedule
201
  *
202
- * @param array $schedules
203
  *
204
  * @return array $schedules
205
  */
206
  public function add_weekly_schedule( $schedules = array() ) {
207
 
208
- // Add weekly schedule if not exists already. From WP 5.4, it is added by default.
209
  if ( empty( $schedules['weekly'] ) ) {
210
  $schedules['weekly'] = array(
211
  'interval' => DAY_IN_SECONDS * 7,
@@ -215,7 +215,7 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
215
 
216
  return $schedules;
217
  }
218
-
219
  /**
220
  * Schedule cron
221
  */
@@ -244,22 +244,22 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
244
  }
245
 
246
  $show_tracking_notice = apply_filters( $this->plugin_abbr . '_show_plugin_usage_tracking_notice', false );
247
-
248
  if ( false === $show_tracking_notice ) {
249
  return;
250
  }
251
 
252
  $tracking_allowed = $this->is_tracking_allowed();
253
-
254
  // Check if tracking option is set. Can be yes or no if set else empty.
255
  // yes/no indicates the notice has already been shown and user has opted in/out. Don't show the notice in this case.
256
  if ( ! empty( $tracking_allowed ) ) {
257
  return;
258
  }
259
-
260
  $optin_url = wp_nonce_url( add_query_arg( $this->plugin_abbr . '_tracker', 'opt_into' ), $this->plugin_abbr . '_tracker_action' );
261
  $optout_url = wp_nonce_url( add_query_arg( $this->plugin_abbr . '_tracker', 'opt_out' ), $this->plugin_abbr . '_tracker_action' );
262
-
263
  ?>
264
  <style type="text/css">
265
  #ig-plugin-usage-tracker-notice .button {
@@ -329,13 +329,16 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
329
  */
330
  public function get_tracked_data_list() {
331
 
332
- $data = apply_filters( $this->plugin_abbr . '_tracked_data_list', array(
333
- __( 'Server environment details (PHP, MYSQL, Server name etc.)', $this->text_domain ),
334
- __( 'WordPress environment details (Site URL, Site language, Timezone, WordPress version etc.)', $this->text_domain ),
335
- __( 'Installed plugins details', $this->text_domain ),
336
- __( 'Active theme details', $this->text_domain ),
337
- __( 'Admin name and email address', $this->text_domain ),
338
- ) );
 
 
 
339
 
340
  return $data;
341
  }
@@ -344,13 +347,13 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
344
  * Is allow track.
345
  *
346
  * Checks whether the site admin has opted-in for data tracking, or not.
347
- *
348
  * @return bool
349
  */
350
  public function is_tracking_allowed() {
351
  $tracking_option_name = $this->get_tracking_option_name();
352
  $tracking_allowed = get_option( $tracking_option_name, '' );
353
-
354
  // Enable tracking by default if allowed_by_default is true.
355
  if ( empty( $tracking_allowed ) && $this->allowed_by_default ) {
356
  $tracking_allowed = 'yes';
@@ -362,7 +365,7 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
362
 
363
  /**
364
  * Get tracking option name
365
- *
366
  * @return string
367
  */
368
  public function get_tracking_option_name() {
@@ -378,14 +381,14 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
378
  */
379
  public function handle_tracker_notice_actions() {
380
 
381
- if ( ! isset( $_GET[$this->plugin_abbr . '_tracker'] ) ) {
382
  return;
383
  }
384
 
385
  check_admin_referer( $this->plugin_abbr . '_tracker_action' );
386
 
387
  $opted_in = 'no';
388
- if ( 'opt_into' === $_GET[$this->plugin_abbr . '_tracker'] ) {
389
  $opted_in = 'yes';
390
  }
391
 
@@ -397,7 +400,7 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
397
 
398
  /**
399
  * Set tracking option
400
- *
401
  * @param string $opted_in yes/no
402
  */
403
  public function set_opt_in( $opted_in ) {
@@ -407,14 +410,14 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
407
 
408
  /**
409
  * Send tracking data.
410
- *
411
- * @param bool $ignore_last_send Whether to consider last sending time before sending a new request.
412
  * @param array $extra_params Extra request params.
413
  */
414
  public function send_tracking_data( $ignore_last_send = false, $extra_params = array() ) {
415
 
416
  $tracking_allowed = $this->is_tracking_allowed();
417
-
418
  // Return if tracking not allowed
419
  if ( 'yes' !== $tracking_allowed ) {
420
  return;
@@ -422,9 +425,9 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
422
 
423
  if ( ! $ignore_last_send ) {
424
  $last_send = $this->get_last_send_time();
425
-
426
  $last_send_interval = strtotime( '-1 week' );
427
-
428
  // Send a maximum of once per week.
429
  if ( $last_send && $last_send > $last_send_interval ) {
430
  return;
@@ -435,10 +438,10 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
435
  $this->update_last_send_time( time() );
436
 
437
  $params = $this->get_tracking_data();
438
- if ( ! empty( $extra_params ) ) {
439
  $params = array_merge( $params, $extra_params );
440
  }
441
-
442
  if ( ! empty( $params ) && is_array( $params ) ) {
443
 
444
  add_filter( 'https_ssl_verify', '__return_false' );
@@ -484,7 +487,7 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
484
 
485
  /**
486
  * Get tracker class name being used by the plugin
487
- *
488
  * @return string
489
  */
490
  public function get_tracker_class() {
@@ -503,17 +506,17 @@ if ( ! class_exists( 'IG_Plugin_Usage_Tracker_V_1_0_0' ) ) {
503
  $tracker_class = $this->get_tracker_class();
504
 
505
  $params = array(
506
- 'sdk_version' => $this->sdk_version,
507
- 'product_id' => $this->product_id,
508
- 'plan' => $this->plugin_plan,
509
- 'user_info' => $tracker_class::get_user_info(),
510
- 'plugins_info' => array(
511
  'active_plugins' => $tracker_class::get_active_plugins( true ),
512
  'inactive_plugins' => $tracker_class::get_inactive_plugins( true ),
513
  ),
514
- 'current_theme' => $tracker_class::get_current_theme_info(),
515
- 'wp_info' => $tracker_class::get_wp_info(),
516
- 'server_info' => $tracker_class::get_server_info(),
517
  );
518
 
519
  /**
71
 
72
  /**
73
  * IG Tracker class name
74
+ *
75
  * @var string
76
  */
77
  public $tracker_class;
78
 
79
  /**
80
  * Is tracking allowed by default
81
+ *
82
  * @var bool
83
  */
84
  public $allowed_by_default;
107
  $this->allowed_by_default = $allowed_by_default;
108
 
109
  // Don't run usage tracker on dev environment if not enabled.
110
+ if ( $tracker_class::is_dev_environment() && ! $enable_on_dev ) {
111
  return;
112
  }
113
 
115
  register_deactivation_hook( $plugin_file_path, array( $this, 'do_deactivation_cleanup' ) );
116
 
117
  $tracking_option_name = $this->get_tracking_option_name();
118
+
119
  /**
120
  * Tracking consent add/update handler function.
121
  * These action hooks are triggered by WordPress when we add/update tracking consent option in DB.
134
 
135
  /**
136
  * Handles when optin option is added in db
137
+ *
138
  * @param string $option_name
139
  * @param string $value
140
  */
144
 
145
  /**
146
  * Handles when optin option is updated in db
147
+ *
148
  * @param string $old_value
149
  * @param string $new_value
150
  * @param string $option_name
155
 
156
  /**
157
  * Common method to handle optin option add/update
158
+ *
159
  * @param string $value
160
  */
161
  public function handle_optin_change( $opted_in ) {
184
  * Do deactivation cleanup
185
  */
186
  public function do_deactivation_cleanup() {
187
+
188
  $this->clear_scheduled_cron();
189
 
190
  $survey_status = ig_es_get_request_data( 'survey_status', '' );
191
  if ( ! empty( $survey_status ) && 'skipped' === $survey_status ) {
192
  $extra_params = array(
193
+ 'is_deactivated' => 1,
194
  );
195
  $this->send_tracking_data( true, $extra_params );
196
  }
199
  /**
200
  * Add weekly cron schedule
201
  *
202
+ * @param array $schedules
203
  *
204
  * @return array $schedules
205
  */
206
  public function add_weekly_schedule( $schedules = array() ) {
207
 
208
+ // Add weekly schedule if not exists already. From WP 5.4, it is added by default.
209
  if ( empty( $schedules['weekly'] ) ) {
210
  $schedules['weekly'] = array(
211
  'interval' => DAY_IN_SECONDS * 7,
215
 
216
  return $schedules;
217
  }
218
+
219
  /**
220
  * Schedule cron
221
  */
244
  }
245
 
246
  $show_tracking_notice = apply_filters( $this->plugin_abbr . '_show_plugin_usage_tracking_notice', false );
247
+
248
  if ( false === $show_tracking_notice ) {
249
  return;
250
  }
251
 
252
  $tracking_allowed = $this->is_tracking_allowed();
253
+
254
  // Check if tracking option is set. Can be yes or no if set else empty.
255
  // yes/no indicates the notice has already been shown and user has opted in/out. Don't show the notice in this case.
256
  if ( ! empty( $tracking_allowed ) ) {
257
  return;
258
  }
259
+
260
  $optin_url = wp_nonce_url( add_query_arg( $this->plugin_abbr . '_tracker', 'opt_into' ), $this->plugin_abbr . '_tracker_action' );
261
  $optout_url = wp_nonce_url( add_query_arg( $this->plugin_abbr . '_tracker', 'opt_out' ), $this->plugin_abbr . '_tracker_action' );
262
+
263
  ?>
264
  <style type="text/css">
265
  #ig-plugin-usage-tracker-notice .button {
329
  */
330
  public function get_tracked_data_list() {
331
 
332
+ $data = apply_filters(
333
+ $this->plugin_abbr . '_tracked_data_list',
334
+ array(
335
+ __( 'Server environment details (PHP, MYSQL, Server name etc.)', $this->text_domain ),
336
+ __( 'WordPress environment details (Site URL, Site language, Timezone, WordPress version etc.)', $this->text_domain ),
337
+ __( 'Installed plugins details', $this->text_domain ),
338
+ __( 'Active theme details', $this->text_domain ),
339
+ __( 'Admin name and email address', $this->text_domain ),
340
+ )
341
+ );
342
 
343
  return $data;
344
  }
347
  * Is allow track.
348
  *
349
  * Checks whether the site admin has opted-in for data tracking, or not.
350
+ *
351
  * @return bool
352
  */
353
  public function is_tracking_allowed() {
354
  $tracking_option_name = $this->get_tracking_option_name();
355
  $tracking_allowed = get_option( $tracking_option_name, '' );
356
+
357
  // Enable tracking by default if allowed_by_default is true.
358
  if ( empty( $tracking_allowed ) && $this->allowed_by_default ) {
359
  $tracking_allowed = 'yes';
365
 
366
  /**
367
  * Get tracking option name
368
+ *
369
  * @return string
370
  */
371
  public function get_tracking_option_name() {
381
  */
382
  public function handle_tracker_notice_actions() {
383
 
384
+ if ( ! isset( $_GET[ $this->plugin_abbr . '_tracker' ] ) ) {
385
  return;
386
  }
387
 
388
  check_admin_referer( $this->plugin_abbr . '_tracker_action' );
389
 
390
  $opted_in = 'no';
391
+ if ( 'opt_into' === $_GET[ $this->plugin_abbr . '_tracker' ] ) {
392
  $opted_in = 'yes';
393
  }
394
 
400
 
401
  /**
402
  * Set tracking option
403
+ *
404
  * @param string $opted_in yes/no
405
  */
406
  public function set_opt_in( $opted_in ) {
410
 
411
  /**
412
  * Send tracking data.
413
+ *
414
+ * @param bool $ignore_last_send Whether to consider last sending time before sending a new request.
415
  * @param array $extra_params Extra request params.
416
  */
417
  public function send_tracking_data( $ignore_last_send = false, $extra_params = array() ) {
418
 
419
  $tracking_allowed = $this->is_tracking_allowed();
420
+
421
  // Return if tracking not allowed
422
  if ( 'yes' !== $tracking_allowed ) {
423
  return;
425
 
426
  if ( ! $ignore_last_send ) {
427
  $last_send = $this->get_last_send_time();
428
+
429
  $last_send_interval = strtotime( '-1 week' );
430
+
431
  // Send a maximum of once per week.
432
  if ( $last_send && $last_send > $last_send_interval ) {
433
  return;
438
  $this->update_last_send_time( time() );
439
 
440
  $params = $this->get_tracking_data();
441
+ if ( ! empty( $extra_params ) ) {
442
  $params = array_merge( $params, $extra_params );
443
  }
444
+
445
  if ( ! empty( $params ) && is_array( $params ) ) {
446
 
447
  add_filter( 'https_ssl_verify', '__return_false' );
487
 
488
  /**
489
  * Get tracker class name being used by the plugin
490
+ *
491
  * @return string
492
  */
493
  public function get_tracker_class() {
506
  $tracker_class = $this->get_tracker_class();
507
 
508
  $params = array(
509
+ 'sdk_version' => $this->sdk_version,
510
+ 'product_id' => $this->product_id,
511
+ 'plan' => $this->plugin_plan,
512
+ 'user_info' => $tracker_class::get_user_info(),
513
+ 'plugins_info' => array(
514
  'active_plugins' => $tracker_class::get_active_plugins( true ),
515
  'inactive_plugins' => $tracker_class::get_inactive_plugins( true ),
516
  ),
517
+ 'current_theme' => $tracker_class::get_current_theme_info(),
518
+ 'wp_info' => $tracker_class::get_wp_info(),
519
+ 'server_info' => $tracker_class::get_server_info(),
520
  );
521
 
522
  /**
lite/includes/feedback/class-ig-tracker.php CHANGED
@@ -30,7 +30,7 @@ if ( ! class_exists( 'IG_Tracker_V_1_2_6' ) ) {
30
 
31
  $plugins = array(
32
  'active_plugins' => array(),
33
- 'inactive_plugins' => array()
34
  );
35
 
36
  // Check if get_plugins() function exists. This is required on the front end of the
@@ -65,7 +65,7 @@ if ( ! class_exists( 'IG_Tracker_V_1_2_6' ) ) {
65
  'author' => $plugin['Author'],
66
  'author_uri' => $plugin['AuthorURI'],
67
  'plugin_uri' => $plugin['PluginURI'],
68
- 'is_active' => $is_active
69
  );
70
 
71
  $plugins[ $slug ][ $plugin_path ] = $plugin_data;
@@ -178,7 +178,7 @@ if ( ! class_exists( 'IG_Tracker_V_1_2_6' ) ) {
178
  'name' => $theme_data->get( 'Name' ),
179
  'version' => $theme_data->get( 'Version' ),
180
  'author' => $theme_data->get( 'Author' ),
181
- 'author_uri' => $theme_data->get( 'AuthorURI' )
182
  );
183
  }
184
 
@@ -198,14 +198,14 @@ if ( ! class_exists( 'IG_Tracker_V_1_2_6' ) ) {
198
  $server_info = array(
199
  'php_version' => PHP_VERSION,
200
  'mysql_version' => $wpdb->db_version(),
201
- 'web_server_info' => isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( $_SERVER['SERVER_SOFTWARE'] ) : '' ,
202
- 'user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) : '' ,
203
  'php_memory_limit' => ini_get( 'memory_limit' ),
204
  'php_post_max_size' => ini_get( 'post_max_size' ),
205
  'php_upload_max_file_size' => ini_get( 'upload_max_filesize' ),
206
  'php_max_execution_time' => ini_get( 'max_execution_time' ),
207
  'php_curl' => function_exists( 'curl_init' ) ? 'yes' : 'no',
208
- 'php_fsockopen' => function_exists( 'fsockopen' ) ? 'yes' : 'no',
209
  'session' => isset( $_SESSION ) ? 'enabled' : 'disabled',
210
  'session_name' => esc_html( ini_get( 'session.name' ) ),
211
  'cookie_path' => esc_html( ini_get( 'session.cookie_path' ) ),
@@ -248,7 +248,7 @@ if ( ! class_exists( 'IG_Tracker_V_1_2_6' ) ) {
248
  'wp_db_charset_Collate' => $wpdb->get_charset_collate(),
249
  'wp_memory_limit' => ( size_format( (int) WP_MEMORY_LIMIT * 1048576 ) ),
250
  'wp_upload_size' => ( size_format( wp_max_upload_size() ) ),
251
- 'filesystem_method' => function_exists('get_filesystem_method') ? get_filesystem_method() : ''
252
  );
253
 
254
  return $wp_info;
@@ -292,7 +292,6 @@ if ( ! class_exists( 'IG_Tracker_V_1_2_6' ) ) {
292
  $is_dev_environment = true;
293
  continue;
294
  }
295
-
296
  }
297
  if ( substr_count( $host, '.' ) > 1 ) {
298
  $subdomains_to_check = array( 'dev.', '*.staging.', 'beta.', 'test.' );
@@ -318,16 +317,18 @@ if ( ! class_exists( 'IG_Tracker_V_1_2_6' ) ) {
318
  * @since 1.2.6
319
  */
320
  public static function get_user_info() {
321
-
322
- $users = get_users( array(
323
- 'role' => 'administrator',
324
- 'orderby' => 'ID',
325
- 'order' => 'ASC',
326
- 'number' => 1,
327
- 'paged' => 1,
328
- ) );
329
-
330
- $admin_user = ( is_array( $users ) && ! empty( $users ) ) ? $users[0]: false;
 
 
331
  $first_name = '';
332
  $last_name = '';
333
 
@@ -337,9 +338,9 @@ if ( ! class_exists( 'IG_Tracker_V_1_2_6' ) ) {
337
  }
338
 
339
  $user_info = array(
340
- 'admin_email' => get_option( 'admin_email' ),
341
- 'first_name' => $first_name,
342
- 'last_name' => $last_name,
343
  );
344
 
345
  return $user_info;
30
 
31
  $plugins = array(
32
  'active_plugins' => array(),
33
+ 'inactive_plugins' => array(),
34
  );
35
 
36
  // Check if get_plugins() function exists. This is required on the front end of the
65
  'author' => $plugin['Author'],
66
  'author_uri' => $plugin['AuthorURI'],
67
  'plugin_uri' => $plugin['PluginURI'],
68
+ 'is_active' => $is_active,
69
  );
70
 
71
  $plugins[ $slug ][ $plugin_path ] = $plugin_data;
178
  'name' => $theme_data->get( 'Name' ),
179
  'version' => $theme_data->get( 'Version' ),
180
  'author' => $theme_data->get( 'Author' ),
181
+ 'author_uri' => $theme_data->get( 'AuthorURI' ),
182
  );
183
  }
184
 
198
  $server_info = array(
199
  'php_version' => PHP_VERSION,
200
  'mysql_version' => $wpdb->db_version(),
201
+ 'web_server_info' => isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( $_SERVER['SERVER_SOFTWARE'] ) : '',
202
+ 'user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) : '',
203
  'php_memory_limit' => ini_get( 'memory_limit' ),
204
  'php_post_max_size' => ini_get( 'post_max_size' ),
205
  'php_upload_max_file_size' => ini_get( 'upload_max_filesize' ),
206
  'php_max_execution_time' => ini_get( 'max_execution_time' ),
207
  'php_curl' => function_exists( 'curl_init' ) ? 'yes' : 'no',
208
+ 'php_fsockopen' => function_exists( 'fsockopen' ) ? 'yes' : 'no',
209
  'session' => isset( $_SESSION ) ? 'enabled' : 'disabled',
210
  'session_name' => esc_html( ini_get( 'session.name' ) ),
211
  'cookie_path' => esc_html( ini_get( 'session.cookie_path' ) ),
248
  'wp_db_charset_Collate' => $wpdb->get_charset_collate(),
249
  'wp_memory_limit' => ( size_format( (int) WP_MEMORY_LIMIT * 1048576 ) ),
250
  'wp_upload_size' => ( size_format( wp_max_upload_size() ) ),
251
+ 'filesystem_method' => function_exists( 'get_filesystem_method' ) ? get_filesystem_method() : '',
252
  );
253
 
254
  return $wp_info;
292
  $is_dev_environment = true;
293
  continue;
294
  }
 
295
  }
296
  if ( substr_count( $host, '.' ) > 1 ) {
297
  $subdomains_to_check = array( 'dev.', '*.staging.', 'beta.', 'test.' );
317
  * @since 1.2.6
318
  */
319
  public static function get_user_info() {
320
+
321
+ $users = get_users(
322
+ array(
323
+ 'role' => 'administrator',
324
+ 'orderby' => 'ID',
325
+ 'order' => 'ASC',
326
+ 'number' => 1,
327
+ 'paged' => 1,
328
+ )
329
+ );
330
+
331
+ $admin_user = ( is_array( $users ) && ! empty( $users ) ) ? $users[0] : false;
332
  $first_name = '';
333
  $last_name = '';
334
 
338
  }
339
 
340
  $user_info = array(
341
+ 'admin_email' => get_option( 'admin_email' ),
342
+ 'first_name' => $first_name,
343
+ 'last_name' => $last_name,
344
  );
345
 
346
  return $user_info;
lite/includes/libraries/action-scheduler/action-scheduler.php CHANGED
@@ -28,7 +28,7 @@
28
  if ( ! function_exists( 'action_scheduler_register_3_dot_1_dot_6' ) ) {
29
 
30
  if ( ! class_exists( 'ActionScheduler_Versions' ) ) {
31
- require_once( 'classes/ActionScheduler_Versions.php' );
32
  add_action( 'plugins_loaded', array( 'ActionScheduler_Versions', 'initialize_latest_version' ), 1, 0 );
33
  }
34
 
@@ -40,7 +40,7 @@ if ( ! function_exists( 'action_scheduler_register_3_dot_1_dot_6' ) ) {
40
  }
41
 
42
  function action_scheduler_initialize_3_dot_1_dot_6() {
43
- require_once( 'classes/abstracts/ActionScheduler.php' );
44
  ActionScheduler::init( __FILE__ );
45
  }
46
 
28
  if ( ! function_exists( 'action_scheduler_register_3_dot_1_dot_6' ) ) {
29
 
30
  if ( ! class_exists( 'ActionScheduler_Versions' ) ) {
31
+ require_once 'classes/ActionScheduler_Versions.php';
32
  add_action( 'plugins_loaded', array( 'ActionScheduler_Versions', 'initialize_latest_version' ), 1, 0 );
33
  }
34
 
40
  }
41
 
42
  function action_scheduler_initialize_3_dot_1_dot_6() {
43
+ require_once 'classes/abstracts/ActionScheduler.php';
44
  ActionScheduler::init( __FILE__ );
45
  }
46
 
lite/includes/libraries/action-scheduler/classes/ActionScheduler_ActionClaim.php CHANGED
@@ -4,11 +4,11 @@
4
  * Class ActionScheduler_ActionClaim
5
  */
6
  class ActionScheduler_ActionClaim {
7
- private $id = '';
8
  private $action_ids = array();
9
 
10
  public function __construct( $id, array $action_ids ) {
11
- $this->id = $id;
12
  $this->action_ids = $action_ids;
13
  }
14
 
@@ -20,4 +20,4 @@ class ActionScheduler_ActionClaim {
20
  return $this->action_ids;
21
  }
22
  }
23
-
4
  * Class ActionScheduler_ActionClaim
5
  */
6
  class ActionScheduler_ActionClaim {
7
+ private $id = '';
8
  private $action_ids = array();
9
 
10
  public function __construct( $id, array $action_ids ) {
11
+ $this->id = $id;
12
  $this->action_ids = $action_ids;
13
  }
14
 
20
  return $this->action_ids;
21
  }
22
  }
23
+
lite/includes/libraries/action-scheduler/classes/ActionScheduler_ActionFactory.php CHANGED
@@ -6,27 +6,27 @@
6
  class ActionScheduler_ActionFactory {
7
 
8
  /**
9
- * @param string $status The action's status in the data store
10
- * @param string $hook The hook to trigger when this action runs
11
- * @param array $args Args to pass to callbacks when the hook is triggered
12
  * @param ActionScheduler_Schedule $schedule The action's schedule
13
- * @param string $group A group to put the action in
14
  *
15
  * @return ActionScheduler_Action An instance of the stored action
16
  */
17
  public function get_stored_action( $status, $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) {
18
 
19
  switch ( $status ) {
20
- case ActionScheduler_Store::STATUS_PENDING :
21
  $action_class = 'ActionScheduler_Action';
22
  break;
23
- case ActionScheduler_Store::STATUS_CANCELED :
24
  $action_class = 'ActionScheduler_CanceledAction';
25
  if ( ! is_null( $schedule ) && ! is_a( $schedule, 'ActionScheduler_CanceledSchedule' ) && ! is_a( $schedule, 'ActionScheduler_NullSchedule' ) ) {
26
  $schedule = new ActionScheduler_CanceledSchedule( $schedule->get_date() );
27
  }
28
  break;
29
- default :
30
  $action_class = 'ActionScheduler_FinishedAction';
31
  break;
32
  }
@@ -58,29 +58,29 @@ class ActionScheduler_ActionFactory {
58
  * claimed by both the existing WP Cron and WP CLI runners, as well as a new async request runner.
59
  *
60
  * @param string $hook The hook to trigger when this action runs
61
- * @param array $args Args to pass when the hook is triggered
62
  * @param string $group A group to put the action in
63
  *
64
  * @return int The ID of the stored action
65
  */
66
  public function async( $hook, $args = array(), $group = '' ) {
67
  $schedule = new ActionScheduler_NullSchedule();
68
- $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
69
  return $this->store( $action );
70
  }
71
 
72
  /**
73
  * @param string $hook The hook to trigger when this action runs
74
- * @param array $args Args to pass when the hook is triggered
75
- * @param int $when Unix timestamp when the action will run
76
  * @param string $group A group to put the action in
77
  *
78
  * @return int The ID of the stored action
79
  */
80
  public function single( $hook, $args = array(), $when = null, $group = '' ) {
81
- $date = as_get_datetime_object( $when );
82
  $schedule = new ActionScheduler_SimpleSchedule( $date );
83
- $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
84
  return $this->store( $action );
85
  }
86
 
@@ -88,20 +88,20 @@ class ActionScheduler_ActionFactory {
88
  * Create the first instance of an action recurring on a given interval.
89
  *
90
  * @param string $hook The hook to trigger when this action runs
91
- * @param array $args Args to pass when the hook is triggered
92
- * @param int $first Unix timestamp for the first run
93
- * @param int $interval Seconds between runs
94
  * @param string $group A group to put the action in
95
  *
96
  * @return int The ID of the stored action
97
  */
98
  public function recurring( $hook, $args = array(), $first = null, $interval = null, $group = '' ) {
99
- if ( empty($interval) ) {
100
  return $this->single( $hook, $args, $first, $group );
101
  }
102
- $date = as_get_datetime_object( $first );
103
  $schedule = new ActionScheduler_IntervalSchedule( $date, $interval );
104
- $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
105
  return $this->store( $action );
106
  }
107
 
@@ -109,23 +109,23 @@ class ActionScheduler_ActionFactory {
109
  * Create the first instance of an action recurring on a Cron schedule.
110
  *
111
  * @param string $hook The hook to trigger when this action runs
112
- * @param array $args Args to pass when the hook is triggered
113
- * @param int $base_timestamp The first instance of the action will be scheduled
114
- * to run at a time calculated after this timestamp matching the cron
115
- * expression. This can be used to delay the first instance of the action.
116
- * @param int $schedule A cron definition string
117
  * @param string $group A group to put the action in
118
  *
119
  * @return int The ID of the stored action
120
  */
121
  public function cron( $hook, $args = array(), $base_timestamp = null, $schedule = null, $group = '' ) {
122
- if ( empty($schedule) ) {
123
  return $this->single( $hook, $args, $base_timestamp, $group );
124
  }
125
- $date = as_get_datetime_object( $base_timestamp );
126
- $cron = CronExpression::factory( $schedule );
127
  $schedule = new ActionScheduler_CronSchedule( $date, $cron );
128
- $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
129
  return $this->store( $action );
130
  }
131
 
@@ -162,8 +162,8 @@ class ActionScheduler_ActionFactory {
162
  }
163
 
164
  $schedule_class = get_class( $schedule );
165
- $new_schedule = new $schedule( $next, $schedule->get_recurrence(), $schedule->get_first_date() );
166
- $new_action = new ActionScheduler_Action( $action->get_hook(), $action->get_args(), $new_schedule, $action->get_group() );
167
  return $this->store( $new_action );
168
  }
169
 
6
  class ActionScheduler_ActionFactory {
7
 
8
  /**
9
+ * @param string $status The action's status in the data store
10
+ * @param string $hook The hook to trigger when this action runs
11
+ * @param array $args Args to pass to callbacks when the hook is triggered
12
  * @param ActionScheduler_Schedule $schedule The action's schedule
13
+ * @param string $group A group to put the action in
14
  *
15
  * @return ActionScheduler_Action An instance of the stored action
16
  */
17
  public function get_stored_action( $status, $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) {
18
 
19
  switch ( $status ) {
20
+ case ActionScheduler_Store::STATUS_PENDING:
21
  $action_class = 'ActionScheduler_Action';
22
  break;
23
+ case ActionScheduler_Store::STATUS_CANCELED:
24
  $action_class = 'ActionScheduler_CanceledAction';
25
  if ( ! is_null( $schedule ) && ! is_a( $schedule, 'ActionScheduler_CanceledSchedule' ) && ! is_a( $schedule, 'ActionScheduler_NullSchedule' ) ) {
26
  $schedule = new ActionScheduler_CanceledSchedule( $schedule->get_date() );
27
  }
28
  break;
29
+ default:
30
  $action_class = 'ActionScheduler_FinishedAction';
31
  break;
32
  }
58
  * claimed by both the existing WP Cron and WP CLI runners, as well as a new async request runner.
59
  *
60
  * @param string $hook The hook to trigger when this action runs
61
+ * @param array $args Args to pass when the hook is triggered
62
  * @param string $group A group to put the action in
63
  *
64
  * @return int The ID of the stored action
65
  */
66
  public function async( $hook, $args = array(), $group = '' ) {
67
  $schedule = new ActionScheduler_NullSchedule();
68
+ $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
69
  return $this->store( $action );
70
  }
71
 
72
  /**
73
  * @param string $hook The hook to trigger when this action runs
74
+ * @param array $args Args to pass when the hook is triggered
75
+ * @param int $when Unix timestamp when the action will run
76
  * @param string $group A group to put the action in
77
  *
78
  * @return int The ID of the stored action
79
  */
80
  public function single( $hook, $args = array(), $when = null, $group = '' ) {
81
+ $date = as_get_datetime_object( $when );
82
  $schedule = new ActionScheduler_SimpleSchedule( $date );
83
+ $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
84
  return $this->store( $action );
85
  }
86
 
88
  * Create the first instance of an action recurring on a given interval.
89
  *
90
  * @param string $hook The hook to trigger when this action runs
91
+ * @param array $args Args to pass when the hook is triggered
92
+ * @param int $first Unix timestamp for the first run
93
+ * @param int $interval Seconds between runs
94
  * @param string $group A group to put the action in
95
  *
96
  * @return int The ID of the stored action
97
  */
98
  public function recurring( $hook, $args = array(), $first = null, $interval = null, $group = '' ) {
99
+ if ( empty( $interval ) ) {
100
  return $this->single( $hook, $args, $first, $group );
101
  }
102
+ $date = as_get_datetime_object( $first );
103
  $schedule = new ActionScheduler_IntervalSchedule( $date, $interval );
104
+ $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
105
  return $this->store( $action );
106
  }
107
 
109
  * Create the first instance of an action recurring on a Cron schedule.
110
  *
111
  * @param string $hook The hook to trigger when this action runs
112
+ * @param array $args Args to pass when the hook is triggered
113
+ * @param int $base_timestamp The first instance of the action will be scheduled
114
+ * to run at a time calculated after this timestamp matching the cron
115
+ * expression. This can be used to delay the first instance of the action.
116
+ * @param int $schedule A cron definition string
117
  * @param string $group A group to put the action in
118
  *
119
  * @return int The ID of the stored action
120
  */
121
  public function cron( $hook, $args = array(), $base_timestamp = null, $schedule = null, $group = '' ) {
122
+ if ( empty( $schedule ) ) {
123
  return $this->single( $hook, $args, $base_timestamp, $group );
124
  }
125
+ $date = as_get_datetime_object( $base_timestamp );
126
+ $cron = CronExpression::factory( $schedule );
127
  $schedule = new ActionScheduler_CronSchedule( $date, $cron );
128
+ $action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
129
  return $this->store( $action );
130
  }
131
 
162
  }
163
 
164
  $schedule_class = get_class( $schedule );
165
+ $new_schedule = new $schedule( $next, $schedule->get_recurrence(), $schedule->get_first_date() );
166
+ $new_action = new ActionScheduler_Action( $action->get_hook(), $action->get_args(), $new_schedule, $action->get_group() );
167
  return $this->store( $new_action );
168
  }
169
 
lite/includes/libraries/action-scheduler/classes/ActionScheduler_AdminView.php CHANGED
@@ -2,11 +2,12 @@
2
 
3
  /**
4
  * Class ActionScheduler_AdminView
 
5
  * @codeCoverageIgnore
6
  */
7
  class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
8
 
9
- private static $admin_view = NULL;
10
 
11
  private static $screen_id = 'tools_page_action-scheduler';
12
 
@@ -20,7 +21,7 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
20
  public static function instance() {
21
 
22
  if ( empty( self::$admin_view ) ) {
23
- $class = apply_filters('action_scheduler_admin_view_class', 'ActionScheduler_AdminView');
24
  self::$admin_view = new $class();
25
  }
26
 
@@ -78,7 +79,7 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
78
  'action-scheduler',
79
  array( $this, 'render_admin_ui' )
80
  );
81
- add_action( 'load-' . $hook_suffix , array( $this, 'process_admin_ui' ) );
82
  }
83
 
84
  /**
2
 
3
  /**
4
  * Class ActionScheduler_AdminView
5
+ *
6
  * @codeCoverageIgnore
7
  */
8
  class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
9
 
10
+ private static $admin_view = null;
11
 
12
  private static $screen_id = 'tools_page_action-scheduler';
13
 
21
  public static function instance() {
22
 
23
  if ( empty( self::$admin_view ) ) {
24
+ $class = apply_filters( 'action_scheduler_admin_view_class', 'ActionScheduler_AdminView' );
25
  self::$admin_view = new $class();
26
  }
27
 
79
  'action-scheduler',
80
  array( $this, 'render_admin_ui' )
81
  );
82
+ add_action( 'load-' . $hook_suffix, array( $this, 'process_admin_ui' ) );
83
  }
84
 
85
  /**
lite/includes/libraries/action-scheduler/classes/ActionScheduler_DataController.php CHANGED
@@ -18,10 +18,10 @@ class ActionScheduler_DataController {
18
  const DATASTORE_CLASS = 'ActionScheduler_DBStore';
19
 
20
  /** Logger data store class name. */
21
- const LOGGER_CLASS = 'ActionScheduler_DBLogger';
22
 
23
  /** Migration status option name. */
24
- const STATUS_FLAG = 'action_scheduler_migration_status';
25
 
26
  /** Migration status option value. */
27
  const STATUS_COMPLETE = 'complete';
18
  const DATASTORE_CLASS = 'ActionScheduler_DBStore';
19
 
20
  /** Logger data store class name. */
21
+ const LOGGER_CLASS = 'ActionScheduler_DBLogger';
22
 
23
  /** Migration status option name. */
24
+ const STATUS_FLAG = 'action_scheduler_migration_status';
25
 
26
  /** Migration status option value. */
27
  const STATUS_COMPLETE = 'complete';
lite/includes/libraries/action-scheduler/classes/ActionScheduler_FatalErrorMonitor.php CHANGED
@@ -5,9 +5,9 @@
5
  */
6
  class ActionScheduler_FatalErrorMonitor {
7
  /** @var ActionScheduler_ActionClaim */
8
- private $claim = NULL;
9
  /** @var ActionScheduler_Store */
10
- private $store = NULL;
11
  private $action_id = 0;
12
 
13
  public function __construct( ActionScheduler_Store $store ) {
@@ -18,19 +18,19 @@ class ActionScheduler_FatalErrorMonitor {
18
  $this->claim = $claim;
19
  add_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
20
  add_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0, 1 );
21
- add_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0, 0 );
22
- add_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0, 0 );
23
- add_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0, 0 );
24
  }
25
 
26
  public function detach() {
27
- $this->claim = NULL;
28
  $this->untrack_action();
29
  remove_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
30
  remove_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0 );
31
- remove_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0 );
32
- remove_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0 );
33
- remove_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0 );
34
  }
35
 
36
  public function track_current_action( $action_id ) {
@@ -44,7 +44,7 @@ class ActionScheduler_FatalErrorMonitor {
44
  public function handle_unexpected_shutdown() {
45
  if ( $error = error_get_last() ) {
46
  if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ) ) ) {
47
- if ( !empty($this->action_id) ) {
48
  $this->store->mark_failure( $this->action_id );
49
  do_action( 'action_scheduler_unexpected_shutdown', $this->action_id, $error );
50
  }
5
  */
6
  class ActionScheduler_FatalErrorMonitor {
7
  /** @var ActionScheduler_ActionClaim */
8
+ private $claim = null;
9
  /** @var ActionScheduler_Store */
10
+ private $store = null;
11
  private $action_id = 0;
12
 
13
  public function __construct( ActionScheduler_Store $store ) {
18
  $this->claim = $claim;
19
  add_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
20
  add_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0, 1 );
21
+ add_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0, 0 );
22
+ add_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0, 0 );
23
+ add_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0, 0 );
24
  }
25
 
26
  public function detach() {
27
+ $this->claim = null;
28
  $this->untrack_action();
29
  remove_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
30
  remove_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0 );
31
+ remove_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0 );
32
+ remove_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0 );
33
+ remove_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0 );
34
  }
35
 
36
  public function track_current_action( $action_id ) {
44
  public function handle_unexpected_shutdown() {
45
  if ( $error = error_get_last() ) {
46
  if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ) ) ) {
47
+ if ( ! empty( $this->action_id ) ) {
48
  $this->store->mark_failure( $this->action_id );
49
  do_action( 'action_scheduler_unexpected_shutdown', $this->action_id, $error );
50
  }
lite/includes/libraries/action-scheduler/classes/ActionScheduler_ListTable.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  /**
4
  * Implements the admin view of the actions.
 
5
  * @codeCoverageIgnore
6
  */
7
  class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
@@ -76,8 +77,8 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
76
  /**
77
  * Sets the current data store object into `store->action` and initialises the object.
78
  *
79
- * @param ActionScheduler_Store $store
80
- * @param ActionScheduler_Logger $logger
81
  * @param ActionScheduler_QueueRunner $runner
82
  */
83
  public function __construct( ActionScheduler_Store $store, ActionScheduler_Logger $logger, ActionScheduler_QueueRunner $runner ) {
@@ -125,9 +126,9 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
125
 
126
  $this->row_actions = array(
127
  'hook' => array(
128
- 'run' => array(
129
- 'name' => __( 'Run', 'action-scheduler' ),
130
- 'desc' => __( 'Process the action now as if it were run as part of a queue', 'action-scheduler' ),
131
  ),
132
  'cancel' => array(
133
  'name' => __( 'Cancel', 'action-scheduler' ),
@@ -175,11 +176,13 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
175
  ),
176
  );
177
 
178
- parent::__construct( array(
179
- 'singular' => 'action-scheduler',
180
- 'plural' => 'action-scheduler',
181
- 'ajax' => false,
182
- ) );
 
 
183
  }
184
 
185
  /**
@@ -211,7 +214,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
211
  if ( ! empty( $output ) ) {
212
  $output .= ' ';
213
  }
214
- $output .= sprintf( _n( self::$time_periods[ $time_period_index ]['names'][0], self::$time_periods[ $time_period_index ]['names'][1], $periods_in_interval, 'action-scheduler' ), $periods_in_interval );
215
  $seconds_remaining -= $periods_in_interval * self::$time_periods[ $time_period_index ]['seconds'];
216
  $periods_included++;
217
  }
@@ -289,7 +292,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
289
  * Prints the logs entries inline. We do so to avoid loading Javascript and other hacks to show it in a modal.
290
  *
291
  * @param ActionScheduler_LogEntry $log_entry
292
- * @param DateTimezone $timezone
293
  * @return string
294
  */
295
  protected function get_log_entry_html( ActionScheduler_LogEntry $log_entry, DateTimezone $timezone ) {
@@ -307,7 +310,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
307
  * @return string
308
  */
309
  protected function maybe_render_actions( $row, $column_name ) {
310
- if ( 'pending' === strtolower( $row[ 'status_name' ] ) ) {
311
  return parent::maybe_render_actions( $row, $column_name );
312
  }
313
 
@@ -338,7 +341,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
338
  if ( ! in_array( $wpdb->prefix . $table_name, $found_tables ) ) {
339
  $this->admin_notices[] = array(
340
  'class' => 'error',
341
- 'message' => __( 'It appears one or more database tables were missing. Attempting to re-create the missing table(s).' , 'action-scheduler' ),
342
  );
343
  $this->recreate_tables();
344
  parent::display_admin_notices();
@@ -369,7 +372,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
369
 
370
  // No lock set or lock expired
371
  if ( false === $async_request_lock_expiration || $async_request_lock_expiration < time() ) {
372
- $in_progress_url = add_query_arg( 'status', 'in-progress', remove_query_arg( 'status' ) );
373
  /* translators: %s: process URL */
374
  $async_request_message = sprintf( __( 'A new queue has begun processing. <a href="%s">View actions in-progress &raquo;</a>', 'action-scheduler' ), esc_url( $in_progress_url ) );
375
  } else {
@@ -388,20 +391,20 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
388
  if ( is_array( $notification ) ) {
389
  delete_transient( 'action_scheduler_admin_notice' );
390
 
391
- $action = $this->store->fetch_action( $notification['action_id'] );
392
  $action_hook_html = '<strong><code>' . $action->get_hook() . '</code></strong>';
393
  if ( 1 == $notification['success'] ) {
394
  $class = 'updated';
395
  switch ( $notification['row_action_type'] ) {
396
- case 'run' :
397
  /* translators: %s: action HTML */
398
  $action_message_html = sprintf( __( 'Successfully executed action: %s', 'action-scheduler' ), $action_hook_html );
399
  break;
400
- case 'cancel' :
401
  /* translators: %s: action HTML */
402
  $action_message_html = sprintf( __( 'Successfully canceled action: %s', 'action-scheduler' ), $action_hook_html );
403
  break;
404
- default :
405
  /* translators: %s: action HTML */
406
  $action_message_html = sprintf( __( 'Successfully processed change for action: %s', 'action-scheduler' ), $action_hook_html );
407
  break;
@@ -470,7 +473,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
470
  * Deletes actions based on their ID. This is the handler for the bulk delete. It assumes the data
471
  * properly validated by the callee and it will delete the actions without any extra validation.
472
  *
473
- * @param array $ids
474
  * @param string $ids_sql Inherited and unused
475
  */
476
  protected function bulk_delete( array $ids, $ids_sql ) {
@@ -520,23 +523,23 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
520
  /**
521
  * Implements the logic behind processing an action once an action link is clicked on the list table.
522
  *
523
- * @param int $action_id
524
  * @param string $row_action_type The type of action to perform on the action.
525
  */
526
  protected function process_row_action( $action_id, $row_action_type ) {
527
  try {
528
  switch ( $row_action_type ) {
529
- case 'run' :
530
  $this->runner->process_action( $action_id, 'Admin List Table' );
531
  break;
532
- case 'cancel' :
533
  $this->store->cancel_action( $action_id );
534
  break;
535
  }
536
- $success = 1;
537
  $error_message = '';
538
  } catch ( Exception $e ) {
539
- $success = 0;
540
  $error_message = $e->getMessage();
541
  }
542
 
@@ -550,7 +553,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
550
  $this->prepare_column_headers();
551
 
552
  $per_page = $this->get_items_per_page( $this->package . '_items_per_page', $this->items_per_page );
553
- $query = array(
554
  'per_page' => $per_page,
555
  'offset' => $this->get_items_offset(),
556
  'status' => $this->get_request_status(),
@@ -588,11 +591,13 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
588
  );
589
  }
590
 
591
- $this->set_pagination_args( array(
592
- 'total_items' => $total_items,
593
- 'per_page' => $per_page,
594
- 'total_pages' => ceil( $total_items / $per_page ),
595
- ) );
 
 
596
  }
597
 
598
  /**
2
 
3
  /**
4
  * Implements the admin view of the actions.
5
+ *
6
  * @codeCoverageIgnore
7
  */
8
  class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
77
  /**
78
  * Sets the current data store object into `store->action` and initialises the object.
79
  *
80
+ * @param ActionScheduler_Store $store
81
+ * @param ActionScheduler_Logger $logger
82
  * @param ActionScheduler_QueueRunner $runner
83
  */
84
  public function __construct( ActionScheduler_Store $store, ActionScheduler_Logger $logger, ActionScheduler_QueueRunner $runner ) {
126
 
127
  $this->row_actions = array(
128
  'hook' => array(
129
+ 'run' => array(
130
+ 'name' => __( 'Run', 'action-scheduler' ),
131
+ 'desc' => __( 'Process the action now as if it were run as part of a queue', 'action-scheduler' ),
132
  ),
133
  'cancel' => array(
134
  'name' => __( 'Cancel', 'action-scheduler' ),
176
  ),
177
  );
178
 
179
+ parent::__construct(
180
+ array(
181
+ 'singular' => 'action-scheduler',
182
+ 'plural' => 'action-scheduler',
183
+ 'ajax' => false,
184
+ )
185
+ );
186
  }
187
 
188
  /**
214
  if ( ! empty( $output ) ) {
215
  $output .= ' ';
216
  }
217
+ $output .= sprintf( _n( self::$time_periods[ $time_period_index ]['names'][0], self::$time_periods[ $time_period_index ]['names'][1], $periods_in_interval, 'action-scheduler' ), $periods_in_interval );
218
  $seconds_remaining -= $periods_in_interval * self::$time_periods[ $time_period_index ]['seconds'];
219
  $periods_included++;
220
  }
292
  * Prints the logs entries inline. We do so to avoid loading Javascript and other hacks to show it in a modal.
293
  *
294
  * @param ActionScheduler_LogEntry $log_entry
295
+ * @param DateTimezone $timezone
296
  * @return string
297
  */
298
  protected function get_log_entry_html( ActionScheduler_LogEntry $log_entry, DateTimezone $timezone ) {
310
  * @return string
311
  */
312
  protected function maybe_render_actions( $row, $column_name ) {
313
+ if ( 'pending' === strtolower( $row['status_name'] ) ) {
314
  return parent::maybe_render_actions( $row, $column_name );
315
  }
316
 
341
  if ( ! in_array( $wpdb->prefix . $table_name, $found_tables ) ) {
342
  $this->admin_notices[] = array(
343
  'class' => 'error',
344
+ 'message' => __( 'It appears one or more database tables were missing. Attempting to re-create the missing table(s).', 'action-scheduler' ),
345
  );
346
  $this->recreate_tables();
347
  parent::display_admin_notices();
372
 
373
  // No lock set or lock expired
374
  if ( false === $async_request_lock_expiration || $async_request_lock_expiration < time() ) {
375
+ $in_progress_url = add_query_arg( 'status', 'in-progress', remove_query_arg( 'status' ) );
376
  /* translators: %s: process URL */
377
  $async_request_message = sprintf( __( 'A new queue has begun processing. <a href="%s">View actions in-progress &raquo;</a>', 'action-scheduler' ), esc_url( $in_progress_url ) );
378
  } else {
391
  if ( is_array( $notification ) ) {
392
  delete_transient( 'action_scheduler_admin_notice' );
393
 
394
+ $action = $this->store->fetch_action( $notification['action_id'] );
395
  $action_hook_html = '<strong><code>' . $action->get_hook() . '</code></strong>';
396
  if ( 1 == $notification['success'] ) {
397
  $class = 'updated';
398
  switch ( $notification['row_action_type'] ) {
399
+ case 'run':
400
  /* translators: %s: action HTML */
401
  $action_message_html = sprintf( __( 'Successfully executed action: %s', 'action-scheduler' ), $action_hook_html );
402
  break;
403
+ case 'cancel':
404
  /* translators: %s: action HTML */
405
  $action_message_html = sprintf( __( 'Successfully canceled action: %s', 'action-scheduler' ), $action_hook_html );
406
  break;
407
+ default:
408
  /* translators: %s: action HTML */
409
  $action_message_html = sprintf( __( 'Successfully processed change for action: %s', 'action-scheduler' ), $action_hook_html );
410
  break;
473
  * Deletes actions based on their ID. This is the handler for the bulk delete. It assumes the data
474
  * properly validated by the callee and it will delete the actions without any extra validation.
475
  *
476
+ * @param array $ids
477
  * @param string $ids_sql Inherited and unused
478
  */
479
  protected function bulk_delete( array $ids, $ids_sql ) {
523
  /**
524
  * Implements the logic behind processing an action once an action link is clicked on the list table.
525
  *
526
+ * @param int $action_id
527
  * @param string $row_action_type The type of action to perform on the action.
528
  */
529
  protected function process_row_action( $action_id, $row_action_type ) {
530
  try {
531
  switch ( $row_action_type ) {
532
+ case 'run':
533
  $this->runner->process_action( $action_id, 'Admin List Table' );
534
  break;
535
+ case 'cancel':
536
  $this->store->cancel_action( $action_id );
537
  break;
538
  }
539
+ $success = 1;
540
  $error_message = '';
541
  } catch ( Exception $e ) {
542
+ $success = 0;
543
  $error_message = $e->getMessage();
544
  }
545
 
553
  $this->prepare_column_headers();
554
 
555
  $per_page = $this->get_items_per_page( $this->package . '_items_per_page', $this->items_per_page );
556
+ $query = array(
557
  'per_page' => $per_page,
558
  'offset' => $this->get_items_offset(),
559
  'status' => $this->get_request_status(),
591
  );
592
  }
593
 
594
+ $this->set_pagination_args(
595
+ array(
596
+ 'total_items' => $total_items,
597
+ 'per_page' => $per_page,
598
+ 'total_pages' => ceil( $total_items / $per_page ),
599
+ )
600
+ );
601
  }
602
 
603
  /**
lite/includes/libraries/action-scheduler/classes/ActionScheduler_LogEntry.php CHANGED
@@ -8,12 +8,12 @@ class ActionScheduler_LogEntry {
8
  /**
9
  * @var int $action_id
10
  */
11
- protected $action_id = '';
12
 
13
  /**
14
  * @var string $message
15
  */
16
- protected $message = '';
17
 
18
  /**
19
  * @var Datetime $date
@@ -23,8 +23,8 @@ class ActionScheduler_LogEntry {
23
  /**
24
  * Constructor
25
  *
26
- * @param mixed $action_id Action ID
27
- * @param string $message Message
28
  * @param Datetime $date Datetime object with the time when this log entry was created. If this parameter is
29
  * not provided a new Datetime object (with current time) will be created.
30
  */
@@ -44,7 +44,7 @@ class ActionScheduler_LogEntry {
44
 
45
  $this->action_id = $action_id;
46
  $this->message = $message;
47
- $this->date = $date ? $date : new Datetime;
48
  }
49
 
50
  /**
8
  /**
9
  * @var int $action_id
10
  */
11
+ protected $action_id = '';
12
 
13
  /**
14
  * @var string $message
15
  */
16
+ protected $message = '';
17
 
18
  /**
19
  * @var Datetime $date
23
  /**
24
  * Constructor
25
  *
26
+ * @param mixed $action_id Action ID
27
+ * @param string $message Message
28
  * @param Datetime $date Datetime object with the time when this log entry was created. If this parameter is
29
  * not provided a new Datetime object (with current time) will be created.
30
  */
44
 
45
  $this->action_id = $action_id;
46
  $this->message = $message;
47
+ $this->date = $date ? $date : new Datetime();
48
  }
49
 
50
  /**
lite/includes/libraries/action-scheduler/classes/ActionScheduler_NullLogEntry.php CHANGED
@@ -8,4 +8,4 @@ class ActionScheduler_NullLogEntry extends ActionScheduler_LogEntry {
8
  // nothing to see here
9
  }
10
  }
11
-
8
  // nothing to see here
9
  }
10
  }
11
+
lite/includes/libraries/action-scheduler/classes/ActionScheduler_OptionLock.php CHANGED
@@ -5,6 +5,7 @@
5
  * for up-to a given duration.
6
  *
7
  * Class ActionScheduler_OptionLock
 
8
  * @since 3.0.0
9
  */
10
  class ActionScheduler_OptionLock extends ActionScheduler_Lock {
5
  * for up-to a given duration.
6
  *
7
  * Class ActionScheduler_OptionLock
8
+ *
9
  * @since 3.0.0
10
  */
11
  class ActionScheduler_OptionLock extends ActionScheduler_Lock {
lite/includes/libraries/action-scheduler/classes/ActionScheduler_QueueCleaner.php CHANGED
@@ -25,13 +25,13 @@ class ActionScheduler_QueueCleaner {
25
  * @param int $batch_size The batch size.
26
  */
27
  public function __construct( ActionScheduler_Store $store = null, $batch_size = 20 ) {
28
- $this->store = $store ? $store : ActionScheduler_Store::instance();
29
  $this->batch_size = $batch_size;
30
  }
31
 
32
  public function delete_old_actions() {
33
  $lifespan = apply_filters( 'action_scheduler_retention_period', $this->month_in_seconds );
34
- $cutoff = as_get_datetime_object($lifespan.' seconds ago');
35
 
36
  $statuses_to_purge = array(
37
  ActionScheduler_Store::STATUS_COMPLETE,
@@ -39,12 +39,14 @@ class ActionScheduler_QueueCleaner {
39
  );
40
 
41
  foreach ( $statuses_to_purge as $status ) {
42
- $actions_to_delete = $this->store->query_actions( array(
43
- 'status' => $status,
44
- 'modified' => $cutoff,
45
- 'modified_compare' => '<=',
46
- 'per_page' => $this->get_batch_size(),
47
- ) );
 
 
48
 
49
  foreach ( $actions_to_delete as $action_id ) {
50
  try {
@@ -83,14 +85,16 @@ class ActionScheduler_QueueCleaner {
83
  if ( $timeout < 0 ) {
84
  return;
85
  }
86
- $cutoff = as_get_datetime_object($timeout.' seconds ago');
87
- $actions_to_reset = $this->store->query_actions( array(
88
- 'status' => ActionScheduler_Store::STATUS_PENDING,
89
- 'modified' => $cutoff,
90
- 'modified_compare' => '<=',
91
- 'claimed' => true,
92
- 'per_page' => $this->get_batch_size(),
93
- ) );
 
 
94
 
95
  foreach ( $actions_to_reset as $action_id ) {
96
  $this->store->unclaim_action( $action_id );
@@ -112,13 +116,15 @@ class ActionScheduler_QueueCleaner {
112
  if ( $timeout < 0 ) {
113
  return;
114
  }
115
- $cutoff = as_get_datetime_object($timeout.' seconds ago');
116
- $actions_to_reset = $this->store->query_actions( array(
117
- 'status' => ActionScheduler_Store::STATUS_RUNNING,
118
- 'modified' => $cutoff,
119
- 'modified_compare' => '<=',
120
- 'per_page' => $this->get_batch_size(),
121
- ) );
 
 
122
 
123
  foreach ( $actions_to_reset as $action_id ) {
124
  $this->store->mark_failure( $action_id );
25
  * @param int $batch_size The batch size.
26
  */
27
  public function __construct( ActionScheduler_Store $store = null, $batch_size = 20 ) {
28
+ $this->store = $store ? $store : ActionScheduler_Store::instance();
29
  $this->batch_size = $batch_size;
30
  }
31
 
32
  public function delete_old_actions() {
33
  $lifespan = apply_filters( 'action_scheduler_retention_period', $this->month_in_seconds );
34
+ $cutoff = as_get_datetime_object( $lifespan . ' seconds ago' );
35
 
36
  $statuses_to_purge = array(
37
  ActionScheduler_Store::STATUS_COMPLETE,
39
  );
40
 
41
  foreach ( $statuses_to_purge as $status ) {
42
+ $actions_to_delete = $this->store->query_actions(
43
+ array(
44
+ 'status' => $status,
45
+ 'modified' => $cutoff,
46
+ 'modified_compare' => '<=',
47
+ 'per_page' => $this->get_batch_size(),
48
+ )
49
+ );
50
 
51
  foreach ( $actions_to_delete as $action_id ) {
52
  try {
85
  if ( $timeout < 0 ) {
86
  return;
87
  }
88
+ $cutoff = as_get_datetime_object( $timeout . ' seconds ago' );
89
+ $actions_to_reset = $this->store->query_actions(
90
+ array(
91
+ 'status' => ActionScheduler_Store::STATUS_PENDING,
92
+ 'modified' => $cutoff,
93
+ 'modified_compare' => '<=',
94
+ 'claimed' => true,
95
+ 'per_page' => $this->get_batch_size(),
96
+ )
97
+ );
98
 
99
  foreach ( $actions_to_reset as $action_id ) {
100
  $this->store->unclaim_action( $action_id );
116
  if ( $timeout < 0 ) {
117
  return;
118
  }
119
+ $cutoff = as_get_datetime_object( $timeout . ' seconds ago' );
120
+ $actions_to_reset = $this->store->query_actions(
121
+ array(
122
+ 'status' => ActionScheduler_Store::STATUS_RUNNING,
123
+ 'modified' => $cutoff,
124
+ 'modified_compare' => '<=',
125
+ 'per_page' => $this->get_batch_size(),
126
+ )
127
+ );
128
 
129
  foreach ( $actions_to_reset as $action_id ) {
130
  $this->store->mark_failure( $action_id );
lite/includes/libraries/action-scheduler/classes/ActionScheduler_QueueRunner.php CHANGED
@@ -19,8 +19,8 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
19
  * @codeCoverageIgnore
20
  */
21
  public static function instance() {
22
- if ( empty(self::$runner) ) {
23
- $class = apply_filters('action_scheduler_queue_runner_class', 'ActionScheduler_QueueRunner');
24
  self::$runner = new $class();
25
  }
26
  return self::$runner;
@@ -114,6 +114,7 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
114
  * that was the only context in which this method was run, and the self::WP_CRON_HOOK hook had no context
115
  * passed along with it. New code calling this method directly, or by triggering the self::WP_CRON_HOOK,
116
  * should set a context as the first parameter. For an example of this, refer to the code seen in
 
117
  * @see ActionScheduler_AsyncRequest_QueueRunner::handle()
118
  *
119
  * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
@@ -144,14 +145,14 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
144
  * Actions are processed by claiming a set of pending actions then processing each one until either the batch
145
  * size is completed, or memory or time limits are reached, defined by @see $this->batch_limits_exceeded().
146
  *
147
- * @param int $size The maximum number of actions to process in the batch.
148
  * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
149
  * Generally, this should be capitalised and not localised as it's a proper noun.
150
  * @return int The number of actions processed.
151
  */
152
  protected function do_batch( $size = 100, $context = '' ) {
153
- $claim = $this->store->stake_claim($size);
154
- $this->monitor->attach($claim);
155
  $processed_actions = 0;
156
 
157
  foreach ( $claim->get_actions() as $action_id ) {
@@ -166,7 +167,7 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
166
  break;
167
  }
168
  }
169
- $this->store->release_claim($claim);
170
  $this->monitor->detach();
171
  $this->clear_caches();
172
  return $processed_actions;
19
  * @codeCoverageIgnore
20
  */
21
  public static function instance() {
22
+ if ( empty( self::$runner ) ) {
23
+ $class = apply_filters( 'action_scheduler_queue_runner_class', 'ActionScheduler_QueueRunner' );
24
  self::$runner = new $class();
25
  }
26
  return self::$runner;
114
  * that was the only context in which this method was run, and the self::WP_CRON_HOOK hook had no context
115
  * passed along with it. New code calling this method directly, or by triggering the self::WP_CRON_HOOK,
116
  * should set a context as the first parameter. For an example of this, refer to the code seen in
117
+ *
118
  * @see ActionScheduler_AsyncRequest_QueueRunner::handle()
119
  *
120
  * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
145
  * Actions are processed by claiming a set of pending actions then processing each one until either the batch
146
  * size is completed, or memory or time limits are reached, defined by @see $this->batch_limits_exceeded().
147
  *
148
+ * @param int $size The maximum number of actions to process in the batch.
149
  * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
150
  * Generally, this should be capitalised and not localised as it's a proper noun.
151
  * @return int The number of actions processed.
152
  */
153
  protected function do_batch( $size = 100, $context = '' ) {
154
+ $claim = $this->store->stake_claim( $size );
155
+ $this->monitor->attach( $claim );
156
  $processed_actions = 0;
157
 
158
  foreach ( $claim->get_actions() as $action_id ) {
167
  break;
168
  }
169
  }
170
+ $this->store->release_claim( $claim );
171
  $this->monitor->detach();
172
  $this->clear_caches();
173
  return $processed_actions;
lite/includes/libraries/action-scheduler/classes/ActionScheduler_Versions.php CHANGED
@@ -7,16 +7,16 @@ class ActionScheduler_Versions {
7
  /**
8
  * @var ActionScheduler_Versions
9
  */
10
- private static $instance = NULL;
11
 
12
  private $versions = array();
13
 
14
  public function register( $version_string, $initialization_callback ) {
15
- if ( isset($this->versions[$version_string]) ) {
16
- return FALSE;
17
  }
18
- $this->versions[$version_string] = $initialization_callback;
19
- return TRUE;
20
  }
21
 
22
  public function get_versions() {
@@ -24,20 +24,20 @@ class ActionScheduler_Versions {
24
  }
25
 
26
  public function latest_version() {
27
- $keys = array_keys($this->versions);
28
- if ( empty($keys) ) {
29
  return false;
30
  }
31
  uasort( $keys, 'version_compare' );
32
- return end($keys);
33
  }
34
 
35
  public function latest_version_callback() {
36
  $latest = $this->latest_version();
37
- if ( empty($latest) || !isset($this->versions[$latest]) ) {
38
  return '__return_null';
39
  }
40
- return $this->versions[$latest];
41
  }
42
 
43
  /**
@@ -45,7 +45,7 @@ class ActionScheduler_Versions {
45
  * @codeCoverageIgnore
46
  */
47
  public static function instance() {
48
- if ( empty(self::$instance) ) {
49
  self::$instance = new self();
50
  }
51
  return self::$instance;
@@ -56,7 +56,7 @@ class ActionScheduler_Versions {
56
  */
57
  public static function initialize_latest_version() {
58
  $self = self::instance();
59
- call_user_func($self->latest_version_callback());
60
  }
61
  }
62
-
7
  /**
8
  * @var ActionScheduler_Versions
9
  */
10
+ private static $instance = null;
11
 
12
  private $versions = array();
13
 
14
  public function register( $version_string, $initialization_callback ) {
15
+ if ( isset( $this->versions[ $version_string ] ) ) {
16
+ return false;
17
  }
18
+ $this->versions[ $version_string ] = $initialization_callback;
19
+ return true;
20
  }
21
 
22
  public function get_versions() {
24
  }
25
 
26
  public function latest_version() {
27
+ $keys = array_keys( $this->versions );
28
+ if ( empty( $keys ) ) {
29
  return false;
30
  }
31
  uasort( $keys, 'version_compare' );
32
+ return end( $keys );
33
  }
34
 
35
  public function latest_version_callback() {
36
  $latest = $this->latest_version();
37
+ if ( empty( $latest ) || ! isset( $this->versions[ $latest ] ) ) {
38
  return '__return_null';
39
  }
40
+ return $this->versions[ $latest ];
41
  }
42
 
43
  /**
45
  * @codeCoverageIgnore
46
  */
47
  public static function instance() {
48
+ if ( empty( self::$instance ) ) {
49
  self::$instance = new self();
50
  }
51
  return self::$instance;
56
  */
57
  public static function initialize_latest_version() {
58
  $self = self::instance();
59
+ call_user_func( $self->latest_version_callback() );
60
  }
61
  }
62
+
lite/includes/libraries/action-scheduler/classes/ActionScheduler_WPCommentCleaner.php CHANGED
@@ -66,7 +66,13 @@ class ActionScheduler_WPCommentCleaner {
66
  * Attached to the migration complete hook 'action_scheduler/migration_complete'.
67
  */
68
  public static function maybe_schedule_cleanup() {
69
- if ( (bool) get_comments( array( 'type' => ActionScheduler_wpCommentLogger::TYPE, 'number' => 1, 'fields' => 'ids' ) ) ) {
 
 
 
 
 
 
70
  update_option( self::$has_logs_option_key, 'yes' );
71
 
72
  if ( ! as_next_scheduled_action( self::$cleanup_hook ) ) {
@@ -80,7 +86,13 @@ class ActionScheduler_WPCommentCleaner {
80
  */
81
  public static function delete_all_action_comments() {
82
  global $wpdb;
83
- $wpdb->delete( $wpdb->comments, array( 'comment_type' => ActionScheduler_wpCommentLogger::TYPE, 'comment_agent' => ActionScheduler_wpCommentLogger::AGENT ) );
 
 
 
 
 
 
84
  delete_option( self::$has_logs_option_key );
85
  }
86
 
@@ -90,7 +102,7 @@ class ActionScheduler_WPCommentCleaner {
90
  public static function register_admin_notice() {
91
  add_action( 'admin_notices', array( __CLASS__, 'print_admin_notice' ) );
92
  }
93
-
94
  /**
95
  * Prints details about the orphaned action logs and includes information on where to learn more.
96
  */
66
  * Attached to the migration complete hook 'action_scheduler/migration_complete'.
67
  */
68
  public static function maybe_schedule_cleanup() {
69
+ if ( (bool) get_comments(
70
+ array(
71
+ 'type' => ActionScheduler_wpCommentLogger::TYPE,
72
+ 'number' => 1,
73
+ 'fields' => 'ids',
74
+ )
75
+ ) ) {
76
  update_option( self::$has_logs_option_key, 'yes' );
77
 
78
  if ( ! as_next_scheduled_action( self::$cleanup_hook ) ) {
86
  */
87
  public static function delete_all_action_comments() {
88
  global $wpdb;
89
+ $wpdb->delete(
90
+ $wpdb->comments,
91
+ array(
92
+ 'comment_type' => ActionScheduler_wpCommentLogger::TYPE,
93
+ 'comment_agent' => ActionScheduler_wpCommentLogger::AGENT,
94
+ )
95
+ );
96
  delete_option( self::$has_logs_option_key );
97
  }
98
 
102
  public static function register_admin_notice() {
103
  add_action( 'admin_notices', array( __CLASS__, 'print_admin_notice' ) );
104
  }
105
+
106
  /**
107
  * Prints details about the orphaned action logs and includes information on where to learn more.
108
  */
lite/includes/libraries/action-scheduler/classes/ActionScheduler_wcSystemStatus.php CHANGED
@@ -67,12 +67,14 @@ class ActionScheduler_wcSystemStatus {
67
 
68
  $order = 'oldest' === $date_type ? 'ASC' : 'DESC';
69
 
70
- $action = $this->store->query_actions( array(
71
- 'claimed' => false,
72
- 'status' => $status,
73
- 'per_page' => 1,
74
- 'order' => $order,
75
- ) );
 
 
76
 
77
  if ( ! empty( $action ) ) {
78
  $date_object = $this->store->get_date( $action[0] );
67
 
68
  $order = 'oldest' === $date_type ? 'ASC' : 'DESC';
69
 
70
+ $action = $this->store->query_actions(
71
+ array(
72
+ 'claimed' => false,
73
+ 'status' => $status,
74
+ 'per_page' => 1,
75
+ 'order' => $order,
76
+ )
77
+ );
78
 
79
  if ( ! empty( $action ) ) {
80
  $date_object = $this->store->get_date( $action[0] );
lite/includes/libraries/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_QueueRunner.php CHANGED
@@ -143,7 +143,7 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
143
  *
144
  * @author Jeremy Pry
145
  *
146
- * @param int $action_id
147
  * @param null|ActionScheduler_Action $action The instance of the action. Default to null for backward compatibility.
148
  */
149
  public function after_execute( $action_id, $action = null ) {
143
  *
144
  * @author Jeremy Pry
145
  *
146
+ * @param int $action_id
147
  * @param null|ActionScheduler_Action $action The instance of the action. Default to null for backward compatibility.
148
  */
149
  public function after_execute( $action_id, $action = null ) {
lite/includes/libraries/action-scheduler/classes/WP_CLI/Migration_Command.php CHANGED
@@ -32,38 +32,42 @@ class Migration_Command extends WP_CLI_Command {
32
  return;
33
  }
34
 
35
- WP_CLI::add_command( 'action-scheduler migrate', [ $this, 'migrate' ], [
36
- 'shortdesc' => 'Migrates actions to the DB tables store',
37
- 'synopsis' => [
38
- [
39
- 'type' => 'assoc',
40
- 'name' => 'batch-size',
41
- 'optional' => true,
42
- 'default' => 100,
43
- 'description' => 'The number of actions to process in each batch',
44
- ],
45
- [
46
- 'type' => 'assoc',
47
- 'name' => 'free-memory-on',
48
- 'optional' => true,
49
- 'default' => 50,
50
- 'description' => 'The number of actions to process between freeing memory. 0 disables freeing memory',
51
- ],
52
- [
53
- 'type' => 'assoc',
54
- 'name' => 'pause',
55
- 'optional' => true,
56
- 'default' => 0,
57
- 'description' => 'The number of seconds to pause when freeing memory',
58
- ],
59
- [
60
- 'type' => 'flag',
61
- 'name' => 'dry-run',
62
- 'optional' => true,
63
- 'description' => 'Reports on the actions that would have been migrated, but does not change any data',
64
- ],
65
- ],
66
- ] );
 
 
 
 
67
  }
68
 
69
  /**
@@ -81,14 +85,14 @@ class Migration_Command extends WP_CLI_Command {
81
  $runner = new Runner( $config );
82
  $runner->init_destination();
83
 
84
- $batch_size = isset( $assoc_args[ 'batch-size' ] ) ? (int) $assoc_args[ 'batch-size' ] : 100;
85
- $free_on = isset( $assoc_args[ 'free-memory-on' ] ) ? (int) $assoc_args[ 'free-memory-on' ] : 50;
86
- $sleep = isset( $assoc_args[ 'pause' ] ) ? (int) $assoc_args[ 'pause' ] : 0;
87
  \ActionScheduler_DataController::set_free_ticks( $free_on );
88
  \ActionScheduler_DataController::set_sleep_time( $sleep );
89
 
90
  do {
91
- $actions_processed = $runner->run( $batch_size );
92
  $this->total_processed += $actions_processed;
93
  } while ( $actions_processed > 0 );
94
 
@@ -109,12 +113,15 @@ class Migration_Command extends WP_CLI_Command {
109
  * @return ActionScheduler\Migration\Config
110
  */
111
  private function get_migration_config( $args ) {
112
- $args = wp_parse_args( $args, [
113
- 'dry-run' => false,
114
- ] );
 
 
 
115
 
116
  $config = Controller::instance()->get_migration_config_object();
117
- $config->set_dry_run( ! empty( $args[ 'dry-run' ] ) );
118
 
119
  return $config;
120
  }
@@ -123,26 +130,61 @@ class Migration_Command extends WP_CLI_Command {
123
  * Hook command line logging into migration actions.
124
  */
125
  private function init_logging() {
126
- add_action( 'action_scheduler/migrate_action_dry_run', function ( $action_id ) {
127
- WP_CLI::debug( sprintf( 'Dry-run: migrated action %d', $action_id ) );
128
- }, 10, 1 );
129
- add_action( 'action_scheduler/no_action_to_migrate', function ( $action_id ) {
130
- WP_CLI::debug( sprintf( 'No action found to migrate for ID %d', $action_id ) );
131
- }, 10, 1 );
132
- add_action( 'action_scheduler/migrate_action_failed', function ( $action_id ) {
133
- WP_CLI::warning( sprintf( 'Failed migrating action with ID %d', $action_id ) );
134
- }, 10, 1 );
135
- add_action( 'action_scheduler/migrate_action_incomplete', function ( $source_id, $destination_id ) {
136
- WP_CLI::warning( sprintf( 'Unable to remove source action with ID %d after migrating to new ID %d', $source_id, $destination_id ) );
137
- }, 10, 2 );
138
- add_action( 'action_scheduler/migrated_action', function ( $source_id, $destination_id ) {
139
- WP_CLI::debug( sprintf( 'Migrated source action with ID %d to new store with ID %d', $source_id, $destination_id ) );
140
- }, 10, 2 );
141
- add_action( 'action_scheduler/migration_batch_starting', function ( $batch ) {
142
- WP_CLI::debug( 'Beginning migration of batch: ' . print_r( $batch, true ) );
143
- }, 10, 1 );
144
- add_action( 'action_scheduler/migration_batch_complete', function ( $batch ) {
145
- WP_CLI::log( sprintf( 'Completed migration of %d actions', count( $batch ) ) );
146
- }, 10, 1 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  }
148
  }
32
  return;
33
  }
34
 
35
+ WP_CLI::add_command(
36
+ 'action-scheduler migrate',
37
+ array( $this, 'migrate' ),
38
+ array(
39
+ 'shortdesc' => 'Migrates actions to the DB tables store',
40
+ 'synopsis' => array(
41
+ array(
42
+ 'type' => 'assoc',
43
+ 'name' => 'batch-size',
44
+ 'optional' => true,
45
+ 'default' => 100,
46
+ 'description' => 'The number of actions to process in each batch',
47
+ ),
48
+ array(
49
+ 'type' => 'assoc',
50
+ 'name' => 'free-memory-on',
51
+ 'optional' => true,
52
+ 'default' => 50,
53
+ 'description' => 'The number of actions to process between freeing memory. 0 disables freeing memory',
54
+ ),
55
+ array(
56
+ 'type' => 'assoc',
57
+ 'name' => 'pause',
58
+ 'optional' => true,
59
+ 'default' => 0,
60
+ 'description' => 'The number of seconds to pause when freeing memory',
61
+ ),
62
+ array(
63
+ 'type' => 'flag',
64
+ 'name' => 'dry-run',
65
+ 'optional' => true,
66
+ 'description' => 'Reports on the actions that would have been migrated, but does not change any data',
67
+ ),
68
+ ),
69
+ )
70
+ );
71
  }
72
 
73
  /**
85
  $runner = new Runner( $config );
86
  $runner->init_destination();
87
 
88
+ $batch_size = isset( $assoc_args['batch-size'] ) ? (int) $assoc_args['batch-size'] : 100;
89
+ $free_on = isset( $assoc_args['free-memory-on'] ) ? (int) $assoc_args['free-memory-on'] : 50;
90
+ $sleep = isset( $assoc_args['pause'] ) ? (int) $assoc_args['pause'] : 0;
91
  \ActionScheduler_DataController::set_free_ticks( $free_on );
92
  \ActionScheduler_DataController::set_sleep_time( $sleep );
93
 
94
  do {
95
+ $actions_processed = $runner->run( $batch_size );
96
  $this->total_processed += $actions_processed;
97
  } while ( $actions_processed > 0 );
98
 
113
  * @return ActionScheduler\Migration\Config
114
  */
115
  private function get_migration_config( $args ) {
116
+ $args = wp_parse_args(
117
+ $args,
118
+ array(
119
+ 'dry-run' => false,
120
+ )
121
+ );
122
 
123
  $config = Controller::instance()->get_migration_config_object();
124
+ $config->set_dry_run( ! empty( $args['dry-run'] ) );
125
 
126
  return $config;
127
  }
130
  * Hook command line logging into migration actions.
131
  */
132
  private function init_logging() {
133
+ add_action(
134
+ 'action_scheduler/migrate_action_dry_run',
135
+ function ( $action_id ) {
136
+ WP_CLI::debug( sprintf( 'Dry-run: migrated action %d', $action_id ) );
137
+ },
138
+ 10,
139
+ 1
140
+ );
141
+ add_action(
142
+ 'action_scheduler/no_action_to_migrate',
143
+ function ( $action_id ) {
144
+ WP_CLI::debug( sprintf( 'No action found to migrate for ID %d', $action_id ) );
145
+ },
146
+ 10,
147
+ 1
148
+ );
149
+ add_action(
150
+ 'action_scheduler/migrate_action_failed',
151
+ function ( $action_id ) {
152
+ WP_CLI::warning( sprintf( 'Failed migrating action with ID %d', $action_id ) );
153
+ },
154
+ 10,
155
+ 1
156
+ );
157
+ add_action(
158
+ 'action_scheduler/migrate_action_incomplete',
159
+ function ( $source_id, $destination_id ) {
160
+ WP_CLI::warning( sprintf( 'Unable to remove source action with ID %d after migrating to new ID %d', $source_id, $destination_id ) );
161
+ },
162
+ 10,
163
+ 2
164
+ );
165
+ add_action(
166
+ 'action_scheduler/migrated_action',
167
+ function ( $source_id, $destination_id ) {
168
+ WP_CLI::debug( sprintf( 'Migrated source action with ID %d to new store with ID %d', $source_id, $destination_id ) );
169
+ },
170
+ 10,
171
+ 2
172
+ );
173
+ add_action(
174
+ 'action_scheduler/migration_batch_starting',
175
+ function ( $batch ) {
176
+ WP_CLI::debug( 'Beginning migration of batch: ' . print_r( $batch, true ) );
177
+ },
178
+ 10,
179
+ 1
180
+ );
181
+ add_action(
182
+ 'action_scheduler/migration_batch_complete',
183
+ function ( $batch ) {
184
+ WP_CLI::log( sprintf( 'Completed migration of %d actions', count( $batch ) ) );
185
+ },
186
+ 10,
187
+ 1
188
+ );
189
  }
190
  }
lite/includes/libraries/action-scheduler/classes/WP_CLI/ProgressBar.php CHANGED
@@ -38,7 +38,7 @@ class ProgressBar {
38
  * @param string $message Text to display before the progress bar.
39
  * @param integer $count Total number of ticks to be performed.
40
  * @param integer $interval Optional. The interval in milliseconds between updates. Default 100.
41
- *
42
  * @throws Exception When this is not run within WP CLI
43
  */
44
  public function __construct( $message, $count, $interval = 100 ) {
38
  * @param string $message Text to display before the progress bar.
39
  * @param integer $count Total number of ticks to be performed.
40
  * @param integer $interval Optional. The interval in milliseconds between updates. Default 100.
41
+ *
42
  * @throws Exception When this is not run within WP CLI
43
  */
44
  public function __construct( $message, $count, $interval = 100 ) {
lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler.php CHANGED
@@ -5,17 +5,18 @@ use Action_Scheduler\Migration\Controller;
5
 
6
  /**
7
  * Class ActionScheduler
 
8
  * @codeCoverageIgnore
9
  */
10
  abstract class ActionScheduler {
11
  private static $plugin_file = '';
12
  /** @var ActionScheduler_ActionFactory */
13
- private static $factory = NULL;
14
  /** @var bool */
15
  private static $data_store_initialized = false;
16
 
17
  public static function factory() {
18
- if ( !isset(self::$factory) ) {
19
  self::$factory = new ActionScheduler_ActionFactory();
20
  }
21
  return self::$factory;
@@ -43,27 +44,29 @@ abstract class ActionScheduler {
43
 
44
  /**
45
  * Get the absolute system path to the plugin directory, or a file therein
 
46
  * @static
47
  * @param string $path
48
  * @return string
49
  */
50
  public static function plugin_path( $path ) {
51
- $base = dirname(self::$plugin_file);
52
  if ( $path ) {
53
- return trailingslashit($base).$path;
54
  } else {
55
- return untrailingslashit($base);
56
  }
57
  }
58
 
59
  /**
60
  * Get the absolute URL to the plugin directory, or a file therein
 
61
  * @static
62
  * @param string $path
63
  * @return string
64
  */
65
  public static function plugin_url( $path ) {
66
- return plugins_url($path, self::$plugin_file);
67
  }
68
 
69
  public static function autoload( $class ) {
@@ -91,7 +94,7 @@ abstract class ActionScheduler {
91
  $dir = $classes_dir . 'schema' . $d;
92
  } elseif ( strpos( $class, 'ActionScheduler' ) === 0 ) {
93
  $segments = explode( '_', $class );
94
- $type = isset( $segments[ 1 ] ) ? $segments[ 1 ] : '';
95
 
96
  switch ( $type ) {
97
  case 'WPCLI':
@@ -119,7 +122,7 @@ abstract class ActionScheduler {
119
  }
120
 
121
  if ( file_exists( "{$dir}{$class}.php" ) ) {
122
- include( "{$dir}{$class}.php" );
123
  return;
124
  }
125
  }
@@ -139,7 +142,7 @@ abstract class ActionScheduler {
139
  */
140
  do_action( 'action_scheduler_pre_init' );
141
 
142
- require_once( self::plugin_path( 'functions.php' ) );
143
  ActionScheduler_DataController::init();
144
 
145
  $store = self::store();
@@ -161,7 +164,7 @@ abstract class ActionScheduler {
161
  }
162
 
163
  if ( apply_filters( 'action_scheduler_load_deprecated_functions', true ) ) {
164
- require_once( self::plugin_path( 'deprecated/functions.php' ) );
165
  }
166
 
167
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
@@ -248,7 +251,7 @@ abstract class ActionScheduler {
248
  );
249
 
250
  $segments = explode( '_', $class );
251
- $segment = isset( $segments[ 1 ] ) ? $segments[ 1 ] : $class;
252
 
253
  return isset( $migration_segments[ $segment ] ) && $migration_segments[ $segment ];
254
  }
@@ -270,17 +273,17 @@ abstract class ActionScheduler {
270
  );
271
 
272
  $segments = explode( '_', $class );
273
- $segment = isset( $segments[ 1 ] ) ? $segments[ 1 ] : $class;
274
 
275
  return isset( $cli_segments[ $segment ] ) && $cli_segments[ $segment ];
276
  }
277
 
278
  final public function __clone() {
279
- trigger_error("Singleton. No cloning allowed!", E_USER_ERROR);
280
  }
281
 
282
  final public function __wakeup() {
283
- trigger_error("Singleton. No serialization allowed!", E_USER_ERROR);
284
  }
285
 
286
  final private function __construct() {}
5
 
6
  /**
7
  * Class ActionScheduler
8
+ *
9
  * @codeCoverageIgnore
10
  */
11
  abstract class ActionScheduler {
12
  private static $plugin_file = '';
13
  /** @var ActionScheduler_ActionFactory */
14
+ private static $factory = null;
15
  /** @var bool */
16
  private static $data_store_initialized = false;
17
 
18
  public static function factory() {
19
+ if ( ! isset( self::$factory ) ) {
20
  self::$factory = new ActionScheduler_ActionFactory();
21
  }
22
  return self::$factory;
44
 
45
  /**
46
  * Get the absolute system path to the plugin directory, or a file therein
47
+ *
48
  * @static
49
  * @param string $path
50
  * @return string
51
  */
52
  public static function plugin_path( $path ) {
53
+ $base = dirname( self::$plugin_file );
54
  if ( $path ) {
55
+ return trailingslashit( $base ) . $path;
56
  } else {
57
+ return untrailingslashit( $base );
58
  }
59
  }
60
 
61
  /**
62
  * Get the absolute URL to the plugin directory, or a file therein
63
+ *
64
  * @static
65
  * @param string $path
66
  * @return string
67
  */
68
  public static function plugin_url( $path ) {
69
+ return plugins_url( $path, self::$plugin_file );
70
  }
71
 
72
  public static function autoload( $class ) {
94
  $dir = $classes_dir . 'schema' . $d;
95
  } elseif ( strpos( $class, 'ActionScheduler' ) === 0 ) {
96
  $segments = explode( '_', $class );
97
+ $type = isset( $segments[1] ) ? $segments[1] : '';
98
 
99
  switch ( $type ) {
100
  case 'WPCLI':
122
  }
123
 
124
  if ( file_exists( "{$dir}{$class}.php" ) ) {
125
+ include "{$dir}{$class}.php";
126
  return;
127
  }
128
  }
142
  */
143
  do_action( 'action_scheduler_pre_init' );
144
 
145
+ require_once self::plugin_path( 'functions.php' );
146
  ActionScheduler_DataController::init();
147
 
148
  $store = self::store();
164
  }
165
 
166
  if ( apply_filters( 'action_scheduler_load_deprecated_functions', true ) ) {
167
+ require_once self::plugin_path( 'deprecated/functions.php' );
168
  }
169
 
170
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
251
  );
252
 
253
  $segments = explode( '_', $class );
254
+ $segment = isset( $segments[1] ) ? $segments[1] : $class;
255
 
256
  return isset( $migration_segments[ $segment ] ) && $migration_segments[ $segment ];
257
  }
273
  );
274
 
275
  $segments = explode( '_', $class );
276
+ $segment = isset( $segments[1] ) ? $segments[1] : $class;
277
 
278
  return isset( $cli_segments[ $segment ] ) && $cli_segments[ $segment ];
279
  }
280
 
281
  final public function __clone() {
282
+ trigger_error( 'Singleton. No cloning allowed!', E_USER_ERROR );
283
  }
284
 
285
  final public function __wakeup() {
286
+ trigger_error( 'Singleton. No serialization allowed!', E_USER_ERROR );
287
  }
288
 
289
  final private function __construct() {}
lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Abstract_ListTable.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
 
3
  if ( ! class_exists( 'WP_List_Table' ) ) {
4
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
5
  }
6
 
7
  /**
@@ -13,8 +13,8 @@ if ( ! class_exists( 'WP_List_Table' ) ) {
13
  * which columns needs to be shown, filter, ordered by and more and forget about the details.
14
  *
15
  * This class supports:
16
- * - Bulk actions
17
- * - Search
18
  * - Sortable columns
19
  * - Automatic translations of the columns
20
  *
@@ -105,7 +105,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
105
  /**
106
  * Makes translation easier, it basically just wraps
107
  * `_x` with some default (the package name).
108
- *
109
  * @deprecated 3.0.0
110
  */
111
  protected function translate( $text, $context = '' ) {
@@ -146,16 +146,18 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
146
 
147
  check_admin_referer( 'bulk-' . $this->_args['plural'] );
148
 
149
- $method = 'bulk_' . $action;
150
  if ( array_key_exists( $action, $this->bulk_actions ) && is_callable( array( $this, $method ) ) && ! empty( $_GET['ID'] ) && is_array( $_GET['ID'] ) ) {
151
  $ids_sql = '(' . implode( ',', array_fill( 0, count( $_GET['ID'] ), '%s' ) ) . ')';
152
  $this->$method( $_GET['ID'], $wpdb->prepare( $ids_sql, $_GET['ID'] ) );
153
  }
154
 
155
- wp_redirect( remove_query_arg(
156
- array( '_wp_http_referer', '_wpnonce', 'ID', 'action', 'action2' ),
157
- wp_unslash( $_SERVER['REQUEST_URI'] )
158
- ) );
 
 
159
  exit;
160
  }
161
 
@@ -227,7 +229,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
227
  * @return int
228
  */
229
  protected function get_items_offset() {
230
- $per_page = $this->get_items_per_page( $this->package . '_items_per_page', $this->items_per_page );
231
  $current_page = $this->get_pagenum();
232
  if ( 1 < $current_page ) {
233
  $offset = $per_page * ( $current_page - 1 );
@@ -355,9 +357,9 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
355
  return '';
356
  }
357
 
358
- $filter = array();
359
  foreach ( $this->search_by as $column ) {
360
- $filter[] = $wpdb->prepare('`' . $column . '` like "%%s%"', $wpdb->esc_like( $_GET['s'] ));
361
  }
362
  return implode( ' OR ', $filter );
363
  }
@@ -414,14 +416,16 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
414
  $limit = $this->get_items_query_limit();
415
  $offset = $this->get_items_query_offset();
416
  $order = $this->get_items_query_order();
417
- $where = array_filter(array(
418
- $this->get_items_query_search(),
419
- $this->get_items_query_filters(),
420
- ));
 
 
421
  $columns = '`' . implode( '`, `', $this->get_table_columns() ) . '`';
422
 
423
  if ( ! empty( $where ) ) {
424
- $where = 'WHERE ('. implode( ') AND (', $where ) . ')';
425
  } else {
426
  $where = '';
427
  }
@@ -433,11 +437,13 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
433
  $query_count = "SELECT COUNT({$this->ID}) FROM {$this->table_name} {$where}";
434
  $total_items = $wpdb->get_var( $query_count );
435
  $per_page = $this->get_items_per_page( $this->package . '_items_per_page', $this->items_per_page );
436
- $this->set_pagination_args( array(
437
- 'total_items' => $total_items,
438
- 'per_page' => $per_page,
439
- 'total_pages' => ceil( $total_items / $per_page ),
440
- ) );
 
 
441
  }
442
 
443
  public function extra_tablenav( $which ) {
@@ -456,7 +462,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
456
  echo '<select name="filter_by[' . esc_attr( $id ) . ']" class="first" id="filter-by-' . esc_attr( $id ) . '">';
457
 
458
  foreach ( $options as $value => $label ) {
459
- echo '<option value="' . esc_attr( $value ) . '" ' . esc_html( $value == $default ? 'selected' : '' ) .'>'
460
  . esc_html( $label )
461
  . '</option>';
462
  }
@@ -485,7 +491,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
485
  * name transformation though using `$this->ID`.
486
  */
487
  public function column_cb( $row ) {
488
- return '<input name="ID[]" type="checkbox" value="' . esc_attr( $row[ $this->ID ] ) .'" />';
489
  }
490
 
491
  /**
@@ -494,7 +500,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
494
  * This method renders the action menu, it reads the definition from the $row_actions property,
495
  * and it checks that the row action method exists before rendering it.
496
  *
497
- * @param array $row Row to render
498
  * @param $column_name Current row
499
  * @return
500
  */
@@ -505,7 +511,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
505
 
506
  $row_id = $row[ $this->ID ];
507
 
508
- $actions = '<div class="row-actions">';
509
  $action_count = 0;
510
  foreach ( $this->row_actions[ $column_name ] as $action_key => $action ) {
511
 
@@ -515,7 +521,13 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
515
  continue;
516
  }
517
 
518
- $action_link = ! empty( $action['link'] ) ? $action['link'] : add_query_arg( array( 'row_action' => $action_key, 'row_id' => $row_id, 'nonce' => wp_create_nonce( $action_key . '::' . $row_id ) ) );
 
 
 
 
 
 
519
  $span_class = ! empty( $action['class'] ) ? $action['class'] : $action_key;
520
  $separator = ( $action_count < count( $this->row_actions[ $column_name ] ) ) ? ' | ' : '';
521
 
@@ -537,14 +549,16 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
537
 
538
  $method = 'row_action_' . $_REQUEST['row_action'];
539
 
540
- if ( $_REQUEST['nonce'] === wp_create_nonce( $_REQUEST[ 'row_action' ] . '::' . $_REQUEST[ 'row_id' ] ) && method_exists( $this, $method ) ) {
541
  $this->$method( $_REQUEST['row_id'] );
542
  }
543
 
544
- wp_redirect( remove_query_arg(
545
- array( 'row_id', 'row_action', 'nonce' ),
546
- wp_unslash( $_SERVER['REQUEST_URI'] )
547
- ) );
 
 
548
  exit;
549
  }
550
 
@@ -552,7 +566,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
552
  * Default column formatting, it will escape everythig for security.
553
  */
554
  public function column_default( $item, $column_name ) {
555
- $column_html = esc_html( $item[ $column_name ] );
556
  $column_html .= $this->maybe_render_actions( $item, $column_name );
557
  return $column_html;
558
  }
1
  <?php
2
 
3
  if ( ! class_exists( 'WP_List_Table' ) ) {
4
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
5
  }
6
 
7
  /**
13
  * which columns needs to be shown, filter, ordered by and more and forget about the details.
14
  *
15
  * This class supports:
16
+ * - Bulk actions
17
+ * - Search
18
  * - Sortable columns
19
  * - Automatic translations of the columns
20
  *
105
  /**
106
  * Makes translation easier, it basically just wraps
107
  * `_x` with some default (the package name).
108
+ *
109
  * @deprecated 3.0.0
110
  */
111
  protected function translate( $text, $context = '' ) {
146
 
147
  check_admin_referer( 'bulk-' . $this->_args['plural'] );
148
 
149
+ $method = 'bulk_' . $action;
150
  if ( array_key_exists( $action, $this->bulk_actions ) && is_callable( array( $this, $method ) ) && ! empty( $_GET['ID'] ) && is_array( $_GET['ID'] ) ) {
151
  $ids_sql = '(' . implode( ',', array_fill( 0, count( $_GET['ID'] ), '%s' ) ) . ')';
152
  $this->$method( $_GET['ID'], $wpdb->prepare( $ids_sql, $_GET['ID'] ) );
153
  }
154
 
155
+ wp_redirect(
156
+ remove_query_arg(
157
+ array( '_wp_http_referer', '_wpnonce', 'ID', 'action', 'action2' ),
158
+ wp_unslash( $_SERVER['REQUEST_URI'] )
159
+ )
160
+ );
161
  exit;
162
  }
163
 
229
  * @return int
230
  */
231
  protected function get_items_offset() {
232
+ $per_page = $this->get_items_per_page( $this->package . '_items_per_page', $this->items_per_page );
233
  $current_page = $this->get_pagenum();
234
  if ( 1 < $current_page ) {
235
  $offset = $per_page * ( $current_page - 1 );
357
  return '';
358
  }
359
 
360
+ $filter = array();
361
  foreach ( $this->search_by as $column ) {
362
+ $filter[] = $wpdb->prepare( '`' . $column . '` like "%%s%"', $wpdb->esc_like( $_GET['s'] ) );
363
  }
364
  return implode( ' OR ', $filter );
365
  }
416
  $limit = $this->get_items_query_limit();
417
  $offset = $this->get_items_query_offset();
418
  $order = $this->get_items_query_order();
419
+ $where = array_filter(
420
+ array(
421
+ $this->get_items_query_search(),
422
+ $this->get_items_query_filters(),
423
+ )
424
+ );
425
  $columns = '`' . implode( '`, `', $this->get_table_columns() ) . '`';
426
 
427
  if ( ! empty( $where ) ) {
428
+ $where = 'WHERE (' . implode( ') AND (', $where ) . ')';
429
  } else {
430
  $where = '';
431
  }
437
  $query_count = "SELECT COUNT({$this->ID}) FROM {$this->table_name} {$where}";
438
  $total_items = $wpdb->get_var( $query_count );
439
  $per_page = $this->get_items_per_page( $this->package . '_items_per_page', $this->items_per_page );
440
+ $this->set_pagination_args(
441
+ array(
442
+ 'total_items' => $total_items,
443
+ 'per_page' => $per_page,
444
+ 'total_pages' => ceil( $total_items / $per_page ),
445
+ )
446
+ );
447
  }
448
 
449
  public function extra_tablenav( $which ) {
462
  echo '<select name="filter_by[' . esc_attr( $id ) . ']" class="first" id="filter-by-' . esc_attr( $id ) . '">';
463
 
464
  foreach ( $options as $value => $label ) {
465
+ echo '<option value="' . esc_attr( $value ) . '" ' . esc_html( $value == $default ? 'selected' : '' ) . '>'
466
  . esc_html( $label )
467
  . '</option>';
468
  }
491
  * name transformation though using `$this->ID`.
492
  */
493
  public function column_cb( $row ) {
494
+ return '<input name="ID[]" type="checkbox" value="' . esc_attr( $row[ $this->ID ] ) . '" />';
495
  }
496
 
497
  /**
500
  * This method renders the action menu, it reads the definition from the $row_actions property,
501
  * and it checks that the row action method exists before rendering it.
502
  *
503
+ * @param array $row Row to render
504
  * @param $column_name Current row
505
  * @return
506
  */
511
 
512
  $row_id = $row[ $this->ID ];
513
 
514
+ $actions = '<div class="row-actions">';
515
  $action_count = 0;
516
  foreach ( $this->row_actions[ $column_name ] as $action_key => $action ) {
517
 
521
  continue;
522
  }
523
 
524
+ $action_link = ! empty( $action['link'] ) ? $action['link'] : add_query_arg(
525
+ array(
526
+ 'row_action' => $action_key,
527
+ 'row_id' => $row_id,
528
+ 'nonce' => wp_create_nonce( $action_key . '::' . $row_id ),
529
+ )
530
+ );
531
  $span_class = ! empty( $action['class'] ) ? $action['class'] : $action_key;
532
  $separator = ( $action_count < count( $this->row_actions[ $column_name ] ) ) ? ' | ' : '';
533
 
549
 
550
  $method = 'row_action_' . $_REQUEST['row_action'];
551
 
552
+ if ( $_REQUEST['nonce'] === wp_create_nonce( $_REQUEST['row_action'] . '::' . $_REQUEST['row_id'] ) && method_exists( $this, $method ) ) {
553
  $this->$method( $_REQUEST['row_id'] );
554
  }
555
 
556
+ wp_redirect(
557
+ remove_query_arg(
558
+ array( 'row_id', 'row_action', 'nonce' ),
559
+ wp_unslash( $_SERVER['REQUEST_URI'] )
560
+ )
561
+ );
562
  exit;
563
  }
564
 
566
  * Default column formatting, it will escape everythig for security.
567
  */
568
  public function column_default( $item, $column_name ) {
569
+ $column_html = esc_html( $item[ $column_name ] );
570
  $column_html .= $this->maybe_render_actions( $item, $column_name );
571
  return $column_html;
572
  }
lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Abstract_QueueRunner.php CHANGED
@@ -43,7 +43,7 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
43
  /**
44
  * Process an individual action.
45
  *
46
- * @param int $action_id The action ID to process.
47
  * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
48
  * Generally, this should be capitalised and not localised as it's a proper noun.
49
  */
@@ -83,7 +83,7 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
83
  * Schedule the next instance of the action if necessary.
84
  *
85
  * @param ActionScheduler_Action $action
86
- * @param int $action_id
87
  */
88
  protected function schedule_next_instance( ActionScheduler_Action $action, $action_id ) {
89
  try {
43
  /**
44
  * Process an individual action.
45
  *
46
+ * @param int $action_id The action ID to process.
47
  * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
48
  * Generally, this should be capitalised and not localised as it's a proper noun.
49
  */
83
  * Schedule the next instance of the action if necessary.
84
  *
85
  * @param ActionScheduler_Action $action
86
+ * @param int $action_id
87
  */
88
  protected function schedule_next_instance( ActionScheduler_Action $action, $action_id ) {
89
  try {
lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Abstract_RecurringSchedule.php CHANGED
@@ -15,14 +15,14 @@ abstract class ActionScheduler_Abstract_RecurringSchedule extends ActionSchedule
15
  *
16
  * @var DateTime
17
  */
18
- private $first_date = NULL;
19
 
20
  /**
21
  * Timestamp equivalent of @see $this->first_date
22
  *
23
  * @var int
24
  */
25
- protected $first_timestamp = NULL;
26
 
27
  /**
28
  * The recurrance between each time an action is run using this schedule.
@@ -35,8 +35,8 @@ abstract class ActionScheduler_Abstract_RecurringSchedule extends ActionSchedule
35
  protected $recurrence;
36
 
37
  /**
38
- * @param DateTime $date The date & time to run the action.
39
- * @param mixed $recurrence The data used to determine the schedule's recurrance.
40
  * @param DateTime|null $first (Optional) The date & time the first instance of this interval schedule ran. Default null, meaning this is the first instance.
41
  */
42
  public function __construct( DateTime $date, $recurrence, DateTime $first = null ) {
@@ -70,15 +70,19 @@ abstract class ActionScheduler_Abstract_RecurringSchedule extends ActionSchedule
70
 
71
  /**
72
  * For PHP 5.2 compat, since DateTime objects can't be serialized
 
73
  * @return array
74
  */
75
  public function __sleep() {
76
- $sleep_params = parent::__sleep();
77
  $this->first_timestamp = $this->first_date->getTimestamp();
78
- return array_merge( $sleep_params, array(
79
- 'first_timestamp',
80
- 'recurrence'
81
- ) );
 
 
 
82
  }
83
 
84
  /**
15
  *
16
  * @var DateTime
17
  */
18
+ private $first_date = null;
19
 
20
  /**
21
  * Timestamp equivalent of @see $this->first_date
22
  *
23
  * @var int
24
  */
25
+ protected $first_timestamp = null;
26
 
27
  /**
28
  * The recurrance between each time an action is run using this schedule.
35
  protected $recurrence;
36
 
37
  /**
38
+ * @param DateTime $date The date & time to run the action.
39
+ * @param mixed $recurrence The data used to determine the schedule's recurrance.
40
  * @param DateTime|null $first (Optional) The date & time the first instance of this interval schedule ran. Default null, meaning this is the first instance.
41
  */
42
  public function __construct( DateTime $date, $recurrence, DateTime $first = null ) {
70
 
71
  /**
72
  * For PHP 5.2 compat, since DateTime objects can't be serialized
73
+ *
74
  * @return array
75
  */
76
  public function __sleep() {
77
+ $sleep_params = parent::__sleep();
78
  $this->first_timestamp = $this->first_date->getTimestamp();
79
+ return array_merge(
80
+ $sleep_params,
81
+ array(
82
+ 'first_timestamp',
83
+ 'recurrence',
84
+ )
85
+ );
86
  }
87
 
88
  /**
lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Abstract_Schedule.php CHANGED
@@ -10,14 +10,14 @@ abstract class ActionScheduler_Abstract_Schedule extends ActionScheduler_Schedul
10
  *
11
  * @var DateTime
12
  */
13
- private $scheduled_date = NULL;
14
 
15
  /**
16
  * Timestamp equivalent of @see $this->scheduled_date
17
  *
18
  * @var int
19
  */
20
- protected $scheduled_timestamp = NULL;
21
 
22
  /**
23
  * @param DateTime $date The date & time to run the action.
@@ -67,6 +67,7 @@ abstract class ActionScheduler_Abstract_Schedule extends ActionScheduler_Schedul
67
 
68
  /**
69
  * For PHP 5.2 compat, since DateTime objects can't be serialized
 
70
  * @return array
71
  */
72
  public function __sleep() {
10
  *
11
  * @var DateTime
12
  */
13
+ private $scheduled_date = null;
14
 
15
  /**
16
  * Timestamp equivalent of @see $this->scheduled_date
17
  *
18
  * @var int
19
  */
20
+ protected $scheduled_timestamp = null;
21
 
22
  /**
23
  * @param DateTime $date The date & time to run the action.
67
 
68
  /**
69
  * For PHP 5.2 compat, since DateTime objects can't be serialized
70
+ *
71
  * @return array
72
  */
73
  public function __sleep() {
lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Abstract_Schema.php CHANGED
@@ -20,7 +20,7 @@ abstract class ActionScheduler_Abstract_Schema {
20
  /**
21
  * @var array Names of tables that will be registered by this class.
22
  */
23
- protected $tables = [];
24
 
25
  /**
26
  * Register tables with WordPress, and create them if needed.
@@ -72,10 +72,10 @@ abstract class ActionScheduler_Abstract_Schema {
72
  $plugin_option_name = 'schema-';
73
 
74
  switch ( static::class ) {
75
- case 'ActionScheduler_StoreSchema' :
76
  $plugin_option_name .= 'Action_Scheduler\Custom_Tables\DB_Store_Table_Maker';
77
  break;
78
- case 'ActionScheduler_LoggerSchema' :
79
  $plugin_option_name .= 'Action_Scheduler\Custom_Tables\DB_Logger_Table_Maker';
80
  break;
81
  }
@@ -111,7 +111,7 @@ abstract class ActionScheduler_Abstract_Schema {
111
  * @return void
112
  */
113
  private function update_table( $table ) {
114
- require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
115
  $definition = $this->get_table_definition( $table );
116
  if ( $definition ) {
117
  $updated = dbDelta( $definition );
@@ -130,6 +130,6 @@ abstract class ActionScheduler_Abstract_Schema {
130
  * table prefix for the current blog
131
  */
132
  protected function get_full_table_name( $table ) {
133
- return $GLOBALS[ 'wpdb' ]->prefix . $table;
134
  }
135
- }
20
  /**
21
  * @var array Names of tables that will be registered by this class.
22
  */
23
+ protected $tables = array();
24
 
25
  /**
26
  * Register tables with WordPress, and create them if needed.
72
  $plugin_option_name = 'schema-';
73
 
74
  switch ( static::class ) {
75
+ case 'ActionScheduler_StoreSchema':
76
  $plugin_option_name .= 'Action_Scheduler\Custom_Tables\DB_Store_Table_Maker';
77
  break;
78
+ case 'ActionScheduler_LoggerSchema':
79
  $plugin_option_name .= 'Action_Scheduler\Custom_Tables\DB_Logger_Table_Maker';
80
  break;
81
  }
111
  * @return void
112
  */
113
  private function update_table( $table ) {
114
+ require_once ABSPATH . 'wp-admin/includes/upgrade.php';
115
  $definition = $this->get_table_definition( $table );
116
  if ( $definition ) {
117
  $updated = dbDelta( $definition );
130
  * table prefix for the current blog
131
  */
132
  protected function get_full_table_name( $table ) {
133
+ return $GLOBALS['wpdb']->prefix . $table;
134
  }
135
+ }
lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Lock.php CHANGED
@@ -8,7 +8,7 @@
8
  abstract class ActionScheduler_Lock {
9
 
10
  /** @var ActionScheduler_Lock */
11
- private static $locker = NULL;
12
 
13
  /** @var int */
14
  protected static $lock_duration = MINUTE_IN_SECONDS;
@@ -54,7 +54,7 @@ abstract class ActionScheduler_Lock {
54
  */
55
  public static function instance() {
56
  if ( empty( self::$locker ) ) {
57
- $class = apply_filters( 'action_scheduler_lock_class', 'ActionScheduler_OptionLock' );
58
  self::$locker = new $class();
59
  }
60
  return self::$locker;
8
  abstract class ActionScheduler_Lock {
9
 
10
  /** @var ActionScheduler_Lock */
11
+ private static $locker = null;
12
 
13
  /** @var int */
14
  protected static $lock_duration = MINUTE_IN_SECONDS;
54
  */
55
  public static function instance() {
56
  if ( empty( self::$locker ) ) {
57
+ $class = apply_filters( 'action_scheduler_lock_class', 'ActionScheduler_OptionLock' );
58
  self::$locker = new $class();
59
  }
60
  return self::$locker;
lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Logger.php CHANGED
@@ -2,30 +2,31 @@
2
 
3
  /**
4
  * Class ActionScheduler_Logger
 
5
  * @codeCoverageIgnore
6
  */
7
  abstract class ActionScheduler_Logger {
8
- private static $logger = NULL;
9
 
10
  /**
11
  * @return ActionScheduler_Logger
12
  */
13
  public static function instance() {
14
- if ( empty(self::$logger) ) {
15
- $class = apply_filters('action_scheduler_logger_class', 'ActionScheduler_wpCommentLogger');
16
  self::$logger = new $class();
17
  }
18
  return self::$logger;
19
  }
20
 
21
  /**
22
- * @param string $action_id
23
- * @param string $message
24
  * @param DateTime $date
25
  *
26
  * @return string The log entry ID
27
  */
28
- abstract public function log( $action_id, $message, DateTime $date = NULL );
29
 
30
  /**
31
  * @param string $entry_id
@@ -86,7 +87,7 @@ abstract class ActionScheduler_Logger {
86
  $this->log( $action_id, $message );
87
  }
88
 
89
- public function log_completed_action( $action_id, $action = NULL, $context = '' ) {
90
  if ( ! empty( $context ) ) {
91
  /* translators: %s: context */
92
  $message = sprintf( __( 'action complete via %s', 'action-scheduler' ), $context );
@@ -134,12 +135,12 @@ abstract class ActionScheduler_Logger {
134
  }
135
 
136
  /**
137
- * @param string $action_id
138
  * @param Exception|NULL $exception The exception which occured when fetching the action. NULL by default for backward compatibility.
139
  *
140
  * @return ActionScheduler_LogEntry[]
141
  */
142
- public function log_failed_fetch_action( $action_id, Exception $exception = NULL ) {
143
 
144
  if ( ! is_null( $exception ) ) {
145
  /* translators: %s: exception message */
2
 
3
  /**
4
  * Class ActionScheduler_Logger
5
+ *
6
  * @codeCoverageIgnore
7
  */
8
  abstract class ActionScheduler_Logger {
9
+ private static $logger = null;
10
 
11
  /**
12
  * @return ActionScheduler_Logger
13
  */
14
  public static function instance() {
15
+ if ( empty( self::$logger ) ) {
16
+ $class = apply_filters( 'action_scheduler_logger_class', 'ActionScheduler_wpCommentLogger' );
17
  self::$logger = new $class();
18
  }
19
  return self::$logger;
20
  }
21
 
22
  /**
23
+ * @param string $action_id
24
+ * @param string $message
25
  * @param DateTime $date
26
  *
27
  * @return string The log entry ID
28
  */
29
+ abstract public function log( $action_id, $message, DateTime $date = null );
30
 
31
  /**
32
  * @param string $entry_id
87
  $this->log( $action_id, $message );
88
  }
89
 
90
+ public function log_completed_action( $action_id, $action = null, $context = '' ) {
91
  if ( ! empty( $context ) ) {
92
  /* translators: %s: context */
93
  $message = sprintf( __( 'action complete via %s', 'action-scheduler' ), $context );
135
  }
136
 
137
  /**
138
+ * @param string $action_id
139
  * @param Exception|NULL $exception The exception which occured when fetching the action. NULL by default for backward compatibility.
140
  *
141
  * @return ActionScheduler_LogEntry[]
142
  */
143
+ public function log_failed_fetch_action( $action_id, Exception $exception = null ) {
144
 
145
  if ( ! is_null( $exception ) ) {
146
  /* translators: %s: exception message */
lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_Store.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  /**
4
  * Class ActionScheduler_Store
 
5
  * @codeCoverageIgnore
6
  */
7
  abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
@@ -13,20 +14,20 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
13
  const DEFAULT_CLASS = 'ActionScheduler_wpPostStore';
14
 
15
  /** @var ActionScheduler_Store */
16
- private static $store = NULL;
17
 
18
  /** @var int */
19
  protected static $max_args_length = 191;
20
 
21
  /**
22
  * @param ActionScheduler_Action $action
23
- * @param DateTime $scheduled_date Optional Date of the first instance
24
- * to store. Otherwise uses the first date of the action's
25
- * schedule.
26
  *
27
  * @return int The action ID
28
  */
29
- abstract public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = NULL );
30
 
31
  /**
32
  * @param string $action_id
@@ -139,7 +140,7 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
139
  * @return string
140
  */
141
  protected function validate_sql_comparator( $comparison_operator ) {
142
- if ( in_array( $comparison_operator, array('!=', '>', '>=', '<', '<=', '=') ) ) {
143
  return $comparison_operator;
144
  }
145
  return '=';
@@ -149,10 +150,10 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
149
  * Get the time MySQL formated date/time string for an action's (next) scheduled date.
150
  *
151
  * @param ActionScheduler_Action $action
152
- * @param DateTime $scheduled_date (optional)
153
  * @return string
154
  */
155
- protected function get_scheduled_date_string( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
156
  $next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
157
  if ( ! $next ) {
158
  return '0000-00-00 00:00:00';
@@ -166,10 +167,10 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
166
  * Get the time MySQL formated date/time string for an action's (next) scheduled date.
167
  *
168
  * @param ActionScheduler_Action $action
169
- * @param DateTime $scheduled_date (optional)
170
  * @return string
171
  */
172
- protected function get_scheduled_date_string_local( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
173
  $next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
174
  if ( ! $next ) {
175
  return '0000-00-00 00:00:00';
@@ -242,8 +243,8 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
242
  while ( ! empty( $action_ids ) ) {
243
  $action_ids = $this->query_actions(
244
  array(
245
- 'hook' => $hook,
246
- 'status' => self::STATUS_PENDING,
247
  'per_page' => 1000,
248
  )
249
  );
@@ -266,8 +267,8 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
266
  while ( ! empty( $action_ids ) ) {
267
  $action_ids = $this->query_actions(
268
  array(
269
- 'group' => $group,
270
- 'status' => self::STATUS_PENDING,
271
  'per_page' => 1000,
272
  )
273
  );
@@ -310,14 +311,16 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
310
  * Check if there are any pending scheduled actions due to run.
311
  *
312
  * @param ActionScheduler_Action $action
313
- * @param DateTime $scheduled_date (optional)
314
  * @return string
315
  */
316
  public function has_pending_actions_due() {
317
- $pending_actions = $this->query_actions( array(
318
- 'date' => as_get_datetime_object(),
319
- 'status' => ActionScheduler_Store::STATUS_PENDING,
320
- ) );
 
 
321
 
322
  return ! empty( $pending_actions );
323
  }
@@ -337,7 +340,7 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
337
  */
338
  public static function instance() {
339
  if ( empty( self::$store ) ) {
340
- $class = apply_filters( 'action_scheduler_store_class', self::DEFAULT_CLASS );
341
  self::$store = new $class();
342
  }
343
  return self::$store;
2
 
3
  /**
4
  * Class ActionScheduler_Store
5
+ *
6
  * @codeCoverageIgnore
7
  */
8
  abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
14
  const DEFAULT_CLASS = 'ActionScheduler_wpPostStore';
15
 
16
  /** @var ActionScheduler_Store */
17
+ private static $store = null;
18
 
19
  /** @var int */
20
  protected static $max_args_length = 191;
21
 
22
  /**
23
  * @param ActionScheduler_Action $action
24
+ * @param DateTime $scheduled_date Optional Date of the first instance
25
+ * to store. Otherwise uses the first date of the action's
26
+ * schedule.
27
  *
28
  * @return int The action ID
29
  */
30
+ abstract public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = null );
31
 
32
  /**
33
  * @param string $action_id
140
  * @return string
141
  */
142
  protected function validate_sql_comparator( $comparison_operator ) {
143
+ if ( in_array( $comparison_operator, array( '!=', '>', '>=', '<', '<=', '=' ) ) ) {
144
  return $comparison_operator;
145
  }
146
  return '=';
150
  * Get the time MySQL formated date/time string for an action's (next) scheduled date.
151
  *
152
  * @param ActionScheduler_Action $action
153
+ * @param DateTime $scheduled_date (optional)
154
  * @return string
155
  */
156
+ protected function get_scheduled_date_string( ActionScheduler_Action $action, DateTime $scheduled_date = null ) {
157
  $next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
158
  if ( ! $next ) {
159
  return '0000-00-00 00:00:00';
167
  * Get the time MySQL formated date/time string for an action's (next) scheduled date.
168
  *
169
  * @param ActionScheduler_Action $action
170
+ * @param DateTime $scheduled_date (optional)
171
  * @return string
172
  */
173
+ protected function get_scheduled_date_string_local( ActionScheduler_Action $action, DateTime $scheduled_date = null ) {
174
  $next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
175
  if ( ! $next ) {
176
  return '0000-00-00 00:00:00';
243
  while ( ! empty( $action_ids ) ) {
244
  $action_ids = $this->query_actions(
245
  array(
246
+ 'hook' => $hook,
247
+ 'status' => self::STATUS_PENDING,
248
  'per_page' => 1000,
249
  )
250
  );
267
  while ( ! empty( $action_ids ) ) {
268
  $action_ids = $this->query_actions(
269
  array(
270
+ 'group' => $group,
271
+ 'status' => self::STATUS_PENDING,
272
  'per_page' => 1000,
273
  )
274
  );
311
  * Check if there are any pending scheduled actions due to run.
312
  *
313
  * @param ActionScheduler_Action $action
314
+ * @param DateTime $scheduled_date (optional)
315
  * @return string
316
  */
317
  public function has_pending_actions_due() {
318
+ $pending_actions = $this->query_actions(
319
+ array(
320
+ 'date' => as_get_datetime_object(),
321
+ 'status' => self::STATUS_PENDING,
322
+ )
323
+ );
324
 
325
  return ! empty( $pending_actions );
326
  }
340
  */
341
  public static function instance() {
342
  if ( empty( self::$store ) ) {
343
+ $class = apply_filters( 'action_scheduler_store_class', self::DEFAULT_CLASS );
344
  self::$store = new $class();
345
  }
346
  return self::$store;
lite/includes/libraries/action-scheduler/classes/abstracts/ActionScheduler_TimezoneHelper.php CHANGED
@@ -4,7 +4,7 @@
4
  * Class ActionScheduler_TimezoneHelper
5
  */
6
  abstract class ActionScheduler_TimezoneHelper {
7
- private static $local_timezone = NULL;
8
 
9
  /**
10
  * Set a DateTime's timezone to the WordPress site's timezone, or a UTC offset
@@ -99,21 +99,21 @@ abstract class ActionScheduler_TimezoneHelper {
99
  /**
100
  * @deprecated 2.1.0
101
  */
102
- public static function get_local_timezone( $reset = FALSE ) {
103
  _deprecated_function( __FUNCTION__, '2.1.0', 'ActionScheduler_TimezoneHelper::set_local_timezone()' );
104
  if ( $reset ) {
105
- self::$local_timezone = NULL;
106
  }
107
- if ( !isset(self::$local_timezone) ) {
108
- $tzstring = get_option('timezone_string');
109
 
110
- if ( empty($tzstring) ) {
111
- $gmt_offset = get_option('gmt_offset');
112
  if ( $gmt_offset == 0 ) {
113
  $tzstring = 'UTC';
114
  } else {
115
  $gmt_offset *= HOUR_IN_SECONDS;
116
- $tzstring = timezone_name_from_abbr( '', $gmt_offset, 1 );
117
 
118
  // If there's no timezone string, try again with no DST.
119
  if ( false === $tzstring ) {
@@ -145,7 +145,7 @@ abstract class ActionScheduler_TimezoneHelper {
145
  }
146
  }
147
 
148
- self::$local_timezone = new DateTimeZone($tzstring);
149
  }
150
  return self::$local_timezone;
151
  }
4
  * Class ActionScheduler_TimezoneHelper
5
  */
6
  abstract class ActionScheduler_TimezoneHelper {
7
+ private static $local_timezone = null;
8
 
9
  /**
10
  * Set a DateTime's timezone to the WordPress site's timezone, or a UTC offset
99
  /**
100
  * @deprecated 2.1.0
101
  */
102
+ public static function get_local_timezone( $reset = false ) {
103
  _deprecated_function( __FUNCTION__, '2.1.0', 'ActionScheduler_TimezoneHelper::set_local_timezone()' );
104
  if ( $reset ) {
105
+ self::$local_timezone = null;
106
  }
107
+ if ( ! isset( self::$local_timezone ) ) {
108
+ $tzstring = get_option( 'timezone_string' );
109
 
110
+ if ( empty( $tzstring ) ) {
111
+ $gmt_offset = get_option( 'gmt_offset' );
112
  if ( $gmt_offset == 0 ) {
113
  $tzstring = 'UTC';
114
  } else {
115
  $gmt_offset *= HOUR_IN_SECONDS;
116
+ $tzstring = timezone_name_from_abbr( '', $gmt_offset, 1 );
117
 
118
  // If there's no timezone string, try again with no DST.
119
  if ( false === $tzstring ) {
145
  }
146
  }
147
 
148
+ self::$local_timezone = new DateTimeZone( $tzstring );
149
  }
150
  return self::$local_timezone;
151
  }
lite/includes/libraries/action-scheduler/classes/actions/ActionScheduler_Action.php CHANGED
@@ -7,19 +7,19 @@ class ActionScheduler_Action {
7
  protected $hook = '';
8
  protected $args = array();
9
  /** @var ActionScheduler_Schedule */
10
- protected $schedule = NULL;
11
- protected $group = '';
12
 
13
- public function __construct( $hook, array $args = array(), ActionScheduler_Schedule $schedule = NULL, $group = '' ) {
14
  $schedule = empty( $schedule ) ? new ActionScheduler_NullSchedule() : $schedule;
15
- $this->set_hook($hook);
16
- $this->set_schedule($schedule);
17
- $this->set_args($args);
18
- $this->set_group($group);
19
  }
20
 
21
  public function execute() {
22
- return do_action_ref_array($this->get_hook(), $this->get_args());
23
  }
24
 
25
  /**
@@ -70,6 +70,6 @@ class ActionScheduler_Action {
70
  * @return bool If the action has been finished
71
  */
72
  public function is_finished() {
73
- return FALSE;
74
  }
75
  }
7
  protected $hook = '';
8
  protected $args = array();
9
  /** @var ActionScheduler_Schedule */
10
+ protected $schedule = null;
11
+ protected $group = '';
12
 
13
+ public function __construct( $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) {
14
  $schedule = empty( $schedule ) ? new ActionScheduler_NullSchedule() : $schedule;
15
+ $this->set_hook( $hook );
16
+ $this->set_schedule( $schedule );
17
+ $this->set_args( $args );
18
+ $this->set_group( $group );
19
  }
20
 
21
  public function execute() {
22
+ return do_action_ref_array( $this->get_hook(), $this->get_args() );
23
  }
24
 
25
  /**
70
  * @return bool If the action has been finished
71
  */
72
  public function is_finished() {
73
+ return false;
74
  }
75
  }
lite/includes/libraries/action-scheduler/classes/actions/ActionScheduler_CanceledAction.php CHANGED
@@ -9,10 +9,10 @@
9
  class ActionScheduler_CanceledAction extends ActionScheduler_FinishedAction {
10
 
11
  /**
12
- * @param string $hook
13
- * @param array $args
14
  * @param ActionScheduler_Schedule $schedule
15
- * @param string $group
16
  */
17
  public function __construct( $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) {
18
  parent::__construct( $hook, $args, $schedule, $group );
9
  class ActionScheduler_CanceledAction extends ActionScheduler_FinishedAction {
10
 
11
  /**
12
+ * @param string $hook
13
+ * @param array $args
14
  * @param ActionScheduler_Schedule $schedule
15
+ * @param string $group
16
  */
17
  public function __construct( $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) {
18
  parent::__construct( $hook, $args, $schedule, $group );
lite/includes/libraries/action-scheduler/classes/actions/ActionScheduler_FinishedAction.php CHANGED
@@ -10,7 +10,7 @@ class ActionScheduler_FinishedAction extends ActionScheduler_Action {
10
  }
11
 
12
  public function is_finished() {
13
- return TRUE;
14
  }
15
  }
16
-
10
  }
11
 
12
  public function is_finished() {
13
+ return true;
14
  }
15
  }
16
+
lite/includes/libraries/action-scheduler/classes/actions/ActionScheduler_NullAction.php CHANGED
@@ -5,7 +5,7 @@
5
  */
6
  class ActionScheduler_NullAction extends ActionScheduler_Action {
7
 
8
- public function __construct( $hook = '', array $args = array(), ActionScheduler_Schedule $schedule = NULL ) {
9
  $this->set_schedule( new ActionScheduler_NullSchedule() );
10
  }
11
 
@@ -13,4 +13,4 @@ class ActionScheduler_NullAction extends ActionScheduler_Action {
13
  // don't execute
14
  }
15
  }
16
-
5
  */
6
  class ActionScheduler_NullAction extends ActionScheduler_Action {
7
 
8
+ public function __construct( $hook = '', array $args = array(), ActionScheduler_Schedule $schedule = null ) {
9
  $this->set_schedule( new ActionScheduler_NullSchedule() );
10
  }
11
 
13
  // don't execute
14
  }
15
  }
16
+
lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_DBLogger.php CHANGED
@@ -31,12 +31,16 @@ class ActionScheduler_DBLogger extends ActionScheduler_Logger {
31
 
32
  /** @var \wpdb $wpdb */
33
  global $wpdb;
34
- $wpdb->insert( $wpdb->actionscheduler_logs, [
35
- 'action_id' => $action_id,
36
- 'message' => $message,
37
- 'log_date_gmt' => $date_gmt,
38
- 'log_date_local' => $date_local,
39
- ], [ '%d', '%s', '%s', '%s' ] );
 
 
 
 
40
 
41
  return $wpdb->insert_id;
42
  }
@@ -86,7 +90,7 @@ class ActionScheduler_DBLogger extends ActionScheduler_Logger {
86
 
87
  $records = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->actionscheduler_logs} WHERE action_id=%d", $action_id ) );
88
 
89
- return array_map( [ $this, 'create_entry_from_db_record' ], $records );
90
  }
91
 
92
  /**
@@ -101,7 +105,7 @@ class ActionScheduler_DBLogger extends ActionScheduler_Logger {
101
 
102
  parent::init();
103
 
104
- add_action( 'action_scheduler_deleted_action', [ $this, 'clear_deleted_action_logs' ], 10, 1 );
105
  }
106
 
107
  /**
@@ -112,7 +116,7 @@ class ActionScheduler_DBLogger extends ActionScheduler_Logger {
112
  public function clear_deleted_action_logs( $action_id ) {
113
  /** @var \wpdb $wpdb */
114
  global $wpdb;
115
- $wpdb->delete( $wpdb->actionscheduler_logs, [ 'action_id' => $action_id, ], [ '%d' ] );
116
  }
117
 
118
  /**
@@ -134,7 +138,7 @@ class ActionScheduler_DBLogger extends ActionScheduler_Logger {
134
  $message = __( 'action canceled', 'action-scheduler' );
135
  $format = '(%d, ' . $wpdb->prepare( '%s, %s, %s', $message, $date_gmt, $date_local ) . ')';
136
  $sql_query = "INSERT {$wpdb->actionscheduler_logs} (action_id, message, log_date_gmt, log_date_local) VALUES ";
137
- $value_rows = [];
138
 
139
  foreach ( $action_ids as $action_id ) {
140
  $value_rows[] = $wpdb->prepare( $format, $action_id );
31
 
32
  /** @var \wpdb $wpdb */
33
  global $wpdb;
34
+ $wpdb->insert(
35
+ $wpdb->actionscheduler_logs,
36
+ array(
37
+ 'action_id' => $action_id,
38
+ 'message' => $message,
39
+ 'log_date_gmt' => $date_gmt,
40
+ 'log_date_local' => $date_local,
41
+ ),
42
+ array( '%d', '%s', '%s', '%s' )
43
+ );
44
 
45
  return $wpdb->insert_id;
46
  }
90
 
91
  $records = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->actionscheduler_logs} WHERE action_id=%d", $action_id ) );
92
 
93
+ return array_map( array( $this, 'create_entry_from_db_record' ), $records );
94
  }
95
 
96
  /**
105
 
106
  parent::init();
107
 
108
+ add_action( 'action_scheduler_deleted_action', array( $this, 'clear_deleted_action_logs' ), 10, 1 );
109
  }
110
 
111
  /**
116
  public function clear_deleted_action_logs( $action_id ) {
117
  /** @var \wpdb $wpdb */
118
  global $wpdb;
119
+ $wpdb->delete( $wpdb->actionscheduler_logs, array( 'action_id' => $action_id ), array( '%d' ) );
120
  }
121
 
122
  /**
138
  $message = __( 'action canceled', 'action-scheduler' );
139
  $format = '(%d, ' . $wpdb->prepare( '%s, %s, %s', $message, $date_gmt, $date_local ) . ')';
140
  $sql_query = "INSERT {$wpdb->actionscheduler_logs} (action_id, message, log_date_gmt, log_date_local) VALUES ";
141
+ $value_rows = array();
142
 
143
  foreach ( $action_ids as $action_id ) {
144
  $value_rows[] = $wpdb->prepare( $format, $action_id );
lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php CHANGED
@@ -40,14 +40,14 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
40
 
41
  /** @var \wpdb $wpdb */
42
  global $wpdb;
43
- $data = [
44
  'hook' => $action->get_hook(),
45
  'status' => ( $action->is_finished() ? self::STATUS_COMPLETE : self::STATUS_PENDING ),
46
  'scheduled_date_gmt' => $this->get_scheduled_date_string( $action, $date ),
47
  'scheduled_date_local' => $this->get_scheduled_date_string_local( $action, $date ),
48
  'schedule' => serialize( $action->get_schedule() ),
49
  'group_id' => $this->get_group_id( $action->get_group() ),
50
- ];
51
  $args = wp_json_encode( $action->get_args() );
52
  if ( strlen( $args ) <= static::$max_index_length ) {
53
  $data['args'] = $args;
@@ -62,8 +62,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
62
 
63
  if ( is_wp_error( $action_id ) ) {
64
  throw new RuntimeException( $action_id->get_error_message() );
65
- }
66
- elseif ( empty( $action_id ) ) {
67
  throw new RuntimeException( $wpdb->last_error ? $wpdb->last_error : __( 'Database error.', 'action-scheduler' ) );
68
  }
69
 
@@ -103,7 +102,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
103
  * Get a group's ID based on its name/slug.
104
  *
105
  * @param string $slug The string name of a group.
106
- * @param bool $create_if_not_exists Whether to create the group if it does not already exist. Default, true - create the group.
107
  *
108
  * @return int The group's ID, if it exists or is created, or 0 if it does not exist and is not created.
109
  */
@@ -131,7 +130,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
131
  protected function create_group( $slug ) {
132
  /** @var \wpdb $wpdb */
133
  global $wpdb;
134
- $wpdb->insert( $wpdb->actionscheduler_groups, [ 'slug' => $slug ] );
135
 
136
  return (int) $wpdb->insert_id;
137
  }
@@ -146,10 +145,12 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
146
  public function fetch_action( $action_id ) {
147
  /** @var \wpdb $wpdb */
148
  global $wpdb;
149
- $data = $wpdb->get_row( $wpdb->prepare(
150
- "SELECT a.*, g.slug AS `group` FROM {$wpdb->actionscheduler_actions} a LEFT JOIN {$wpdb->actionscheduler_groups} g ON a.group_id=g.group_id WHERE a.action_id=%d",
151
- $action_id
152
- ) );
 
 
153
 
154
  if ( empty( $data ) ) {
155
  return $this->get_null_action();
@@ -211,34 +212,37 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
211
  *
212
  * @return string|null ID of the next action matching the criteria or NULL if not found.
213
  */
214
- public function find_action( $hook, $params = [] ) {
215
- $params = wp_parse_args( $params, [
216
- 'args' => null,
217
- 'status' => self::STATUS_PENDING,
218
- 'group' => '',
219
- ] );
 
 
 
220
 
221
  /** @var wpdb $wpdb */
222
  global $wpdb;
223
  $query = "SELECT a.action_id FROM {$wpdb->actionscheduler_actions} a";
224
- $args = [];
225
- if ( ! empty( $params[ 'group' ] ) ) {
226
- $query .= " INNER JOIN {$wpdb->actionscheduler_groups} g ON g.group_id=a.group_id AND g.slug=%s";
227
- $args[] = $params[ 'group' ];
228
  }
229
- $query .= " WHERE a.hook=%s";
230
  $args[] = $hook;
231
- if ( ! is_null( $params[ 'args' ] ) ) {
232
- $query .= " AND a.args=%s";
233
- $args[] = $this->get_args_for_query( $params[ 'args' ] );
234
  }
235
 
236
  $order = 'ASC';
237
- if ( ! empty( $params[ 'status' ] ) ) {
238
- $query .= " AND a.status=%s";
239
- $args[] = $params[ 'status' ];
240
 
241
- if ( self::STATUS_PENDING == $params[ 'status' ] ) {
242
  $order = 'ASC'; // Find the next action that matches.
243
  } else {
244
  $order = 'DESC'; // Find the most recent action that matches.
@@ -268,89 +272,92 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
268
  throw new InvalidArgumentException( __( 'Invalid value for select or count parameter. Cannot query actions.', 'action-scheduler' ) );
269
  }
270
 
271
- $query = wp_parse_args( $query, [
272
- 'hook' => '',
273
- 'args' => null,
274
- 'date' => null,
275
- 'date_compare' => '<=',
276
- 'modified' => null,
277
- 'modified_compare' => '<=',
278
- 'group' => '',
279
- 'status' => '',
280
- 'claimed' => null,
281
- 'per_page' => 5,
282
- 'offset' => 0,
283
- 'orderby' => 'date',
284
- 'order' => 'ASC',
285
- ] );
 
 
 
286
 
287
  /** @var \wpdb $wpdb */
288
  global $wpdb;
289
- $sql = ( 'count' === $select_or_count ) ? 'SELECT count(a.action_id)' : 'SELECT a.action_id';
290
- $sql .= " FROM {$wpdb->actionscheduler_actions} a";
291
- $sql_params = [];
292
 
293
- if ( ! empty( $query[ 'group' ] ) || 'group' === $query[ 'orderby' ] ) {
294
  $sql .= " LEFT JOIN {$wpdb->actionscheduler_groups} g ON g.group_id=a.group_id";
295
  }
296
 
297
- $sql .= " WHERE 1=1";
298
 
299
- if ( ! empty( $query[ 'group' ] ) ) {
300
- $sql .= " AND g.slug=%s";
301
- $sql_params[] = $query[ 'group' ];
302
  }
303
 
304
- if ( $query[ 'hook' ] ) {
305
- $sql .= " AND a.hook=%s";
306
- $sql_params[] = $query[ 'hook' ];
307
  }
308
- if ( ! is_null( $query[ 'args' ] ) ) {
309
- $sql .= " AND a.args=%s";
310
- $sql_params[] = $this->get_args_for_query( $query[ 'args' ] );
311
  }
312
 
313
- if ( $query[ 'status' ] ) {
314
- $sql .= " AND a.status=%s";
315
- $sql_params[] = $query[ 'status' ];
316
  }
317
 
318
- if ( $query[ 'date' ] instanceof \DateTime ) {
319
- $date = clone $query[ 'date' ];
320
  $date->setTimezone( new \DateTimeZone( 'UTC' ) );
321
  $date_string = $date->format( 'Y-m-d H:i:s' );
322
- $comparator = $this->validate_sql_comparator( $query[ 'date_compare' ] );
323
- $sql .= " AND a.scheduled_date_gmt $comparator %s";
324
  $sql_params[] = $date_string;
325
  }
326
 
327
- if ( $query[ 'modified' ] instanceof \DateTime ) {
328
- $modified = clone $query[ 'modified' ];
329
  $modified->setTimezone( new \DateTimeZone( 'UTC' ) );
330
  $date_string = $modified->format( 'Y-m-d H:i:s' );
331
- $comparator = $this->validate_sql_comparator( $query[ 'modified_compare' ] );
332
- $sql .= " AND a.last_attempt_gmt $comparator %s";
333
  $sql_params[] = $date_string;
334
  }
335
 
336
- if ( $query[ 'claimed' ] === true ) {
337
- $sql .= " AND a.claim_id != 0";
338
- } elseif ( $query[ 'claimed' ] === false ) {
339
- $sql .= " AND a.claim_id = 0";
340
- } elseif ( ! is_null( $query[ 'claimed' ] ) ) {
341
- $sql .= " AND a.claim_id = %d";
342
- $sql_params[] = $query[ 'claimed' ];
343
  }
344
 
345
  if ( ! empty( $query['search'] ) ) {
346
- $sql .= " AND (a.hook LIKE %s OR (a.extended_args IS NULL AND a.args LIKE %s) OR a.extended_args LIKE %s";
347
- for( $i = 0; $i < 3; $i++ ) {
348
  $sql_params[] = sprintf( '%%%s%%', $query['search'] );
349
  }
350
 
351
  $search_claim_id = (int) $query['search'];
352
  if ( $search_claim_id ) {
353
- $sql .= ' OR a.claim_id = %d';
354
  $sql_params[] = $search_claim_id;
355
  }
356
 
@@ -373,16 +380,16 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
373
  $orderby = 'a.scheduled_date_gmt';
374
  break;
375
  }
376
- if ( strtoupper( $query[ 'order' ] ) == 'ASC' ) {
377
  $order = 'ASC';
378
  } else {
379
  $order = 'DESC';
380
  }
381
  $sql .= " ORDER BY $orderby $order";
382
- if ( $query[ 'per_page' ] > 0 ) {
383
- $sql .= " LIMIT %d, %d";
384
- $sql_params[] = $query[ 'offset' ];
385
- $sql_params[] = $query[ 'per_page' ];
386
  }
387
  }
388
 
@@ -401,7 +408,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
401
  *
402
  * @return null|string|array The IDs of actions matching the query
403
  */
404
- public function query_actions( $query = [], $query_type = 'select' ) {
405
  /** @var wpdb $wpdb */
406
  global $wpdb;
407
 
@@ -420,7 +427,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
420
 
421
  $sql = "SELECT a.status, count(a.status) as 'count'";
422
  $sql .= " FROM {$wpdb->actionscheduler_actions} a";
423
- $sql .= " GROUP BY a.status";
424
 
425
  $actions_count_by_status = array();
426
  $action_stati_and_labels = $this->get_status_labels();
@@ -448,10 +455,10 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
448
 
449
  $updated = $wpdb->update(
450
  $wpdb->actionscheduler_actions,
451
- [ 'status' => self::STATUS_CANCELED ],
452
- [ 'action_id' => $action_id ],
453
- [ '%s' ],
454
- [ '%d' ]
455
  );
456
  if ( empty( $updated ) ) {
457
  /* translators: %s: action ID */
@@ -470,7 +477,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
470
  * @return void
471
  */
472
  public function cancel_actions_by_hook( $hook ) {
473
- $this->bulk_cancel_actions( [ 'hook' => $hook ] );
474
  }
475
 
476
  /**
@@ -481,7 +488,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
481
  * @return void
482
  */
483
  public function cancel_actions_by_group( $group ) {
484
- $this->bulk_cancel_actions( [ 'group' => $group ] );
485
  }
486
 
487
  /**
@@ -507,10 +514,10 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
507
  $action_ids = true;
508
  $query_args = wp_parse_args(
509
  $query_args,
510
- [
511
  'per_page' => 1000,
512
- 'status' => self::STATUS_PENDING,
513
- ]
514
  );
515
 
516
  while ( $action_ids ) {
@@ -543,7 +550,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
543
  public function delete_action( $action_id ) {
544
  /** @var \wpdb $wpdb */
545
  global $wpdb;
546
- $deleted = $wpdb->delete( $wpdb->actionscheduler_actions, [ 'action_id' => $action_id ], [ '%d' ] );
547
  if ( empty( $deleted ) ) {
548
  throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
549
  }
@@ -611,7 +618,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
611
  /** @var \wpdb $wpdb */
612
  global $wpdb;
613
  $now = as_get_datetime_object();
614
- $wpdb->insert( $wpdb->actionscheduler_claims, [ 'date_created_gmt' => $now->format( 'Y-m-d H:i:s' ) ] );
615
 
616
  return $wpdb->insert_id;
617
  }
@@ -641,7 +648,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
641
  current_time( 'mysql' ),
642
  );
643
 
644
- $where = "WHERE claim_id = 0 AND scheduled_date_gmt <= %s AND status=%s";
645
  $params[] = $date->format( 'Y-m-d H:i:s' );
646
  $params[] = self::STATUS_PENDING;
647
 
@@ -665,7 +672,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
665
  $params[] = $group_id;
666
  }
667
 
668
- $order = "ORDER BY attempts ASC, scheduled_date_gmt ASC, action_id ASC LIMIT %d";
669
  $params[] = $limit;
670
 
671
  $sql = $wpdb->prepare( "{$update} {$where} {$order}", $params );
@@ -687,7 +694,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
687
  global $wpdb;
688
 
689
  $sql = "SELECT COUNT(DISTINCT claim_id) FROM {$wpdb->actionscheduler_actions} WHERE claim_id != 0 AND status IN ( %s, %s)";
690
- $sql = $wpdb->prepare( $sql, [ self::STATUS_PENDING, self::STATUS_RUNNING ] );
691
 
692
  return (int) $wpdb->get_var( $sql );
693
  }
@@ -735,8 +742,8 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
735
  public function release_claim( ActionScheduler_ActionClaim $claim ) {
736
  /** @var \wpdb $wpdb */
737
  global $wpdb;
738
- $wpdb->update( $wpdb->actionscheduler_actions, [ 'claim_id' => 0 ], [ 'claim_id' => $claim->get_id() ], [ '%d' ], [ '%d' ] );
739
- $wpdb->delete( $wpdb->actionscheduler_claims, [ 'claim_id' => $claim->get_id() ], [ '%d' ] );
740
  }
741
 
742
  /**
@@ -751,10 +758,10 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
751
  global $wpdb;
752
  $wpdb->update(
753
  $wpdb->actionscheduler_actions,
754
- [ 'claim_id' => 0 ],
755
- [ 'action_id' => $action_id ],
756
- [ '%s' ],
757
- [ '%d' ]
758
  );
759
  }
760
 
@@ -768,10 +775,10 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
768
  global $wpdb;
769
  $updated = $wpdb->update(
770
  $wpdb->actionscheduler_actions,
771
- [ 'status' => self::STATUS_FAILED ],
772
- [ 'action_id' => $action_id ],
773
- [ '%s' ],
774
- [ '%d' ]
775
  );
776
  if ( empty( $updated ) ) {
777
  throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
@@ -806,14 +813,14 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
806
  global $wpdb;
807
  $updated = $wpdb->update(
808
  $wpdb->actionscheduler_actions,
809
- [
810
  'status' => self::STATUS_COMPLETE,
811
  'last_attempt_gmt' => current_time( 'mysql', true ),
812
  'last_attempt_local' => current_time( 'mysql' ),
813
- ],
814
- [ 'action_id' => $action_id ],
815
- [ '%s' ],
816
- [ '%d' ]
817
  );
818
  if ( empty( $updated ) ) {
819
  throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
40
 
41
  /** @var \wpdb $wpdb */
42
  global $wpdb;
43
+ $data = array(
44
  'hook' => $action->get_hook(),
45
  'status' => ( $action->is_finished() ? self::STATUS_COMPLETE : self::STATUS_PENDING ),
46
  'scheduled_date_gmt' => $this->get_scheduled_date_string( $action, $date ),
47
  'scheduled_date_local' => $this->get_scheduled_date_string_local( $action, $date ),
48
  'schedule' => serialize( $action->get_schedule() ),
49
  'group_id' => $this->get_group_id( $action->get_group() ),
50
+ );
51
  $args = wp_json_encode( $action->get_args() );
52
  if ( strlen( $args ) <= static::$max_index_length ) {
53
  $data['args'] = $args;
62
 
63
  if ( is_wp_error( $action_id ) ) {
64
  throw new RuntimeException( $action_id->get_error_message() );
65
+ } elseif ( empty( $action_id ) ) {
 
66
  throw new RuntimeException( $wpdb->last_error ? $wpdb->last_error : __( 'Database error.', 'action-scheduler' ) );
67
  }
68
 
102
  * Get a group's ID based on its name/slug.
103
  *
104
  * @param string $slug The string name of a group.
105
+ * @param bool $create_if_not_exists Whether to create the group if it does not already exist. Default, true - create the group.
106
  *
107
  * @return int The group's ID, if it exists or is created, or 0 if it does not exist and is not created.
108
  */
130
  protected function create_group( $slug ) {
131
  /** @var \wpdb $wpdb */
132
  global $wpdb;
133
+ $wpdb->insert( $wpdb->actionscheduler_groups, array( 'slug' => $slug ) );
134
 
135
  return (int) $wpdb->insert_id;
136
  }
145
  public function fetch_action( $action_id ) {
146
  /** @var \wpdb $wpdb */
147
  global $wpdb;
148
+ $data = $wpdb->get_row(
149
+ $wpdb->prepare(
150
+ "SELECT a.*, g.slug AS `group` FROM {$wpdb->actionscheduler_actions} a LEFT JOIN {$wpdb->actionscheduler_groups} g ON a.group_id=g.group_id WHERE a.action_id=%d",
151
+ $action_id
152
+ )
153
+ );
154
 
155
  if ( empty( $data ) ) {
156
  return $this->get_null_action();
212
  *
213
  * @return string|null ID of the next action matching the criteria or NULL if not found.
214
  */
215
+ public function find_action( $hook, $params = array() ) {
216
+ $params = wp_parse_args(
217
+ $params,
218
+ array(
219
+ 'args' => null,
220
+ 'status' => self::STATUS_PENDING,
221
+ 'group' => '',
222
+ )
223
+ );
224
 
225
  /** @var wpdb $wpdb */
226
  global $wpdb;
227
  $query = "SELECT a.action_id FROM {$wpdb->actionscheduler_actions} a";
228
+ $args = array();
229
+ if ( ! empty( $params['group'] ) ) {
230
+ $query .= " INNER JOIN {$wpdb->actionscheduler_groups} g ON g.group_id=a.group_id AND g.slug=%s";
231
+ $args[] = $params['group'];
232
  }
233
+ $query .= ' WHERE a.hook=%s';
234
  $args[] = $hook;
235
+ if ( ! is_null( $params['args'] ) ) {
236
+ $query .= ' AND a.args=%s';
237
+ $args[] = $this->get_args_for_query( $params['args'] );
238
  }
239
 
240
  $order = 'ASC';
241
+ if ( ! empty( $params['status'] ) ) {
242
+ $query .= ' AND a.status=%s';
243
+ $args[] = $params['status'];
244
 
245
+ if ( self::STATUS_PENDING == $params['status'] ) {
246
  $order = 'ASC'; // Find the next action that matches.
247
  } else {
248
  $order = 'DESC'; // Find the most recent action that matches.
272
  throw new InvalidArgumentException( __( 'Invalid value for select or count parameter. Cannot query actions.', 'action-scheduler' ) );
273
  }
274
 
275
+ $query = wp_parse_args(
276
+ $query,
277
+ array(
278
+ 'hook' => '',
279
+ 'args' => null,
280
+ 'date' => null,
281
+ 'date_compare' => '<=',
282
+ 'modified' => null,
283
+ 'modified_compare' => '<=',
284
+ 'group' => '',
285
+ 'status' => '',
286
+ 'claimed' => null,
287
+ 'per_page' => 5,
288
+ 'offset' => 0,
289
+ 'orderby' => 'date',
290
+ 'order' => 'ASC',
291
+ )
292
+ );
293
 
294
  /** @var \wpdb $wpdb */
295
  global $wpdb;
296
+ $sql = ( 'count' === $select_or_count ) ? 'SELECT count(a.action_id)' : 'SELECT a.action_id';
297
+ $sql .= " FROM {$wpdb->actionscheduler_actions} a";
298
+ $sql_params = array();
299
 
300
+ if ( ! empty( $query['group'] ) || 'group' === $query['orderby'] ) {
301
  $sql .= " LEFT JOIN {$wpdb->actionscheduler_groups} g ON g.group_id=a.group_id";
302
  }
303
 
304
+ $sql .= ' WHERE 1=1';
305
 
306
+ if ( ! empty( $query['group'] ) ) {
307
+ $sql .= ' AND g.slug=%s';
308
+ $sql_params[] = $query['group'];
309
  }
310
 
311
+ if ( $query['hook'] ) {
312
+ $sql .= ' AND a.hook=%s';
313
+ $sql_params[] = $query['hook'];
314
  }
315
+ if ( ! is_null( $query['args'] ) ) {
316
+ $sql .= ' AND a.args=%s';
317
+ $sql_params[] = $this->get_args_for_query( $query['args'] );
318
  }
319
 
320
+ if ( $query['status'] ) {
321
+ $sql .= ' AND a.status=%s';
322
+ $sql_params[] = $query['status'];
323
  }
324
 
325
+ if ( $query['date'] instanceof \DateTime ) {
326
+ $date = clone $query['date'];
327
  $date->setTimezone( new \DateTimeZone( 'UTC' ) );
328
  $date_string = $date->format( 'Y-m-d H:i:s' );
329
+ $comparator = $this->validate_sql_comparator( $query['date_compare'] );
330
+ $sql .= " AND a.scheduled_date_gmt $comparator %s";
331
  $sql_params[] = $date_string;
332
  }
333
 
334
+ if ( $query['modified'] instanceof \DateTime ) {
335
+ $modified = clone $query['modified'];
336
  $modified->setTimezone( new \DateTimeZone( 'UTC' ) );
337
  $date_string = $modified->format( 'Y-m-d H:i:s' );
338
+ $comparator = $this->validate_sql_comparator( $query['modified_compare'] );
339
+ $sql .= " AND a.last_attempt_gmt $comparator %s";
340
  $sql_params[] = $date_string;
341
  }
342
 
343
+ if ( $query['claimed'] === true ) {
344
+ $sql .= ' AND a.claim_id != 0';
345
+ } elseif ( $query['claimed'] === false ) {
346
+ $sql .= ' AND a.claim_id = 0';
347
+ } elseif ( ! is_null( $query['claimed'] ) ) {
348
+ $sql .= ' AND a.claim_id = %d';
349
+ $sql_params[] = $query['claimed'];
350
  }
351
 
352
  if ( ! empty( $query['search'] ) ) {
353
+ $sql .= ' AND (a.hook LIKE %s OR (a.extended_args IS NULL AND a.args LIKE %s) OR a.extended_args LIKE %s';
354
+ for ( $i = 0; $i < 3; $i++ ) {
355
  $sql_params[] = sprintf( '%%%s%%', $query['search'] );
356
  }
357
 
358
  $search_claim_id = (int) $query['search'];
359
  if ( $search_claim_id ) {
360
+ $sql .= ' OR a.claim_id = %d';
361
  $sql_params[] = $search_claim_id;
362
  }
363
 
380
  $orderby = 'a.scheduled_date_gmt';
381
  break;
382
  }
383
+ if ( strtoupper( $query['order'] ) == 'ASC' ) {
384
  $order = 'ASC';
385
  } else {
386
  $order = 'DESC';
387
  }
388
  $sql .= " ORDER BY $orderby $order";
389
+ if ( $query['per_page'] > 0 ) {
390
+ $sql .= ' LIMIT %d, %d';
391
+ $sql_params[] = $query['offset'];
392
+ $sql_params[] = $query['per_page'];
393
  }
394
  }
395
 
408
  *
409
  * @return null|string|array The IDs of actions matching the query
410
  */
411
+ public function query_actions( $query = array(), $query_type = 'select' ) {
412
  /** @var wpdb $wpdb */
413
  global $wpdb;
414
 
427
 
428
  $sql = "SELECT a.status, count(a.status) as 'count'";
429
  $sql .= " FROM {$wpdb->actionscheduler_actions} a";
430
+ $sql .= ' GROUP BY a.status';
431
 
432
  $actions_count_by_status = array();
433
  $action_stati_and_labels = $this->get_status_labels();
455
 
456
  $updated = $wpdb->update(
457
  $wpdb->actionscheduler_actions,
458
+ array( 'status' => self::STATUS_CANCELED ),
459
+ array( 'action_id' => $action_id ),
460
+ array( '%s' ),
461
+ array( '%d' )
462
  );
463
  if ( empty( $updated ) ) {
464
  /* translators: %s: action ID */
477
  * @return void
478
  */
479
  public function cancel_actions_by_hook( $hook ) {
480
+ $this->bulk_cancel_actions( array( 'hook' => $hook ) );
481
  }
482
 
483
  /**
488
  * @return void
489
  */
490
  public function cancel_actions_by_group( $group ) {
491
+ $this->bulk_cancel_actions( array( 'group' => $group ) );
492
  }
493
 
494
  /**
514
  $action_ids = true;
515
  $query_args = wp_parse_args(
516
  $query_args,
517
+ array(
518
  'per_page' => 1000,
519
+ 'status' => self::STATUS_PENDING,
520
+ )
521
  );
522
 
523
  while ( $action_ids ) {
550
  public function delete_action( $action_id ) {
551
  /** @var \wpdb $wpdb */
552
  global $wpdb;
553
+ $deleted = $wpdb->delete( $wpdb->actionscheduler_actions, array( 'action_id' => $action_id ), array( '%d' ) );
554
  if ( empty( $deleted ) ) {
555
  throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
556
  }
618
  /** @var \wpdb $wpdb */
619
  global $wpdb;
620
  $now = as_get_datetime_object();
621
+ $wpdb->insert( $wpdb->actionscheduler_claims, array( 'date_created_gmt' => $now->format( 'Y-m-d H:i:s' ) ) );
622
 
623
  return $wpdb->insert_id;
624
  }
648
  current_time( 'mysql' ),
649
  );
650
 
651
+ $where = 'WHERE claim_id = 0 AND scheduled_date_gmt <= %s AND status=%s';
652
  $params[] = $date->format( 'Y-m-d H:i:s' );
653
  $params[] = self::STATUS_PENDING;
654
 
672
  $params[] = $group_id;
673
  }
674
 
675
+ $order = 'ORDER BY attempts ASC, scheduled_date_gmt ASC, action_id ASC LIMIT %d';
676
  $params[] = $limit;
677
 
678
  $sql = $wpdb->prepare( "{$update} {$where} {$order}", $params );
694
  global $wpdb;
695
 
696
  $sql = "SELECT COUNT(DISTINCT claim_id) FROM {$wpdb->actionscheduler_actions} WHERE claim_id != 0 AND status IN ( %s, %s)";
697
+ $sql = $wpdb->prepare( $sql, array( self::STATUS_PENDING, self::STATUS_RUNNING ) );
698
 
699
  return (int) $wpdb->get_var( $sql );
700
  }
742
  public function release_claim( ActionScheduler_ActionClaim $claim ) {
743
  /** @var \wpdb $wpdb */
744
  global $wpdb;
745
+ $wpdb->update( $wpdb->actionscheduler_actions, array( 'claim_id' => 0 ), array( 'claim_id' => $claim->get_id() ), array( '%d' ), array( '%d' ) );
746
+ $wpdb->delete( $wpdb->actionscheduler_claims, array( 'claim_id' => $claim->get_id() ), array( '%d' ) );
747
  }
748
 
749
  /**
758
  global $wpdb;
759
  $wpdb->update(
760
  $wpdb->actionscheduler_actions,
761
+ array( 'claim_id' => 0 ),
762
+ array( 'action_id' => $action_id ),
763
+ array( '%s' ),
764
+ array( '%d' )
765
  );
766
  }
767
 
775
  global $wpdb;
776
  $updated = $wpdb->update(
777
  $wpdb->actionscheduler_actions,
778
+ array( 'status' => self::STATUS_FAILED ),
779
+ array( 'action_id' => $action_id ),
780
+ array( '%s' ),
781
+ array( '%d' )
782
  );
783
  if ( empty( $updated ) ) {
784
  throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
813
  global $wpdb;
814
  $updated = $wpdb->update(
815
  $wpdb->actionscheduler_actions,
816
+ array(
817
  'status' => self::STATUS_COMPLETE,
818
  'last_attempt_gmt' => current_time( 'mysql', true ),
819
  'last_attempt_local' => current_time( 'mysql' ),
820
+ ),
821
+ array( 'action_id' => $action_id ),
822
+ array( '%s' ),
823
+ array( '%d' )
824
  );
825
  if ( empty( $updated ) ) {
826
  throw new \InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_HybridStore.php CHANGED
@@ -53,10 +53,10 @@ class ActionScheduler_HybridStore extends Store {
53
  * @codeCoverageIgnore
54
  */
55
  public function init() {
56
- add_action( 'action_scheduler/created_table', [ $this, 'set_autoincrement' ], 10, 2 );
57
  $this->primary_store->init();
58
  $this->secondary_store->init();
59
- remove_action( 'action_scheduler/created_table', [ $this, 'set_autoincrement' ], 10 );
60
  }
61
 
62
  /**
@@ -78,7 +78,7 @@ class ActionScheduler_HybridStore extends Store {
78
  /** @var \wpdb $wpdb */
79
  global $wpdb;
80
  /**
81
- * A default date of '0000-00-00 00:00:00' is invalid in MySQL 5.7 when configured with
82
  * sql_mode including both STRICT_TRANS_TABLES and NO_ZERO_DATE.
83
  */
84
  $default_date = new DateTime( 'tomorrow' );
@@ -88,7 +88,7 @@ class ActionScheduler_HybridStore extends Store {
88
 
89
  $row_count = $wpdb->insert(
90
  $wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
91
- [
92
  'action_id' => $this->demarkation_id,
93
  'hook' => '',
94
  'status' => '',
@@ -96,12 +96,12 @@ class ActionScheduler_HybridStore extends Store {
96
  'scheduled_date_local' => $date_local,
97
  'last_attempt_gmt' => $date_gmt,
98
  'last_attempt_local' => $date_local,
99
- ]
100
  );
101
  if ( $row_count > 0 ) {
102
  $wpdb->delete(
103
  $wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
104
- [ 'action_id' => $this->demarkation_id ]
105
  );
106
  }
107
  }
@@ -140,10 +140,10 @@ class ActionScheduler_HybridStore extends Store {
140
  *
141
  * @return string
142
  */
143
- public function find_action( $hook, $params = [] ) {
144
  $found_unmigrated_action = $this->secondary_store->find_action( $hook, $params );
145
  if ( ! empty( $found_unmigrated_action ) ) {
146
- $this->migrate( [ $found_unmigrated_action ] );
147
  }
148
 
149
  return $this->primary_store->find_action( $hook, $params );
@@ -154,12 +154,12 @@ class ActionScheduler_HybridStore extends Store {
154
  * If any are found, migrate them immediately. Then the secondary
155
  * store will contain the canonical results.
156
  *
157
- * @param array $query
158
  * @param string $query_type Whether to select or count the results. Default, select.
159
  *
160
  * @return int[]
161
  */
162
- public function query_actions( $query = [], $query_type = 'select' ) {
163
  $found_unmigrated_actions = $this->secondary_store->query_actions( $query, 'select' );
164
  if ( ! empty( $found_unmigrated_actions ) ) {
165
  $this->migrate( $found_unmigrated_actions );
@@ -352,19 +352,19 @@ class ActionScheduler_HybridStore extends Store {
352
  */
353
  protected function get_store_from_action_id( $action_id, $primary_first = false ) {
354
  if ( $primary_first ) {
355
- $stores = [
356
  $this->primary_store,
357
  $this->secondary_store,
358
- ];
359
  } elseif ( $action_id < $this->demarkation_id ) {
360
- $stores = [
361
  $this->secondary_store,
362
  $this->primary_store,
363
- ];
364
  } else {
365
- $stores = [
366
  $this->primary_store,
367
- ];
368
  }
369
 
370
  foreach ( $stores as $store ) {
@@ -376,7 +376,8 @@ class ActionScheduler_HybridStore extends Store {
376
  return null;
377
  }
378
 
379
- /* * * * * * * * * * * * * * * * * * * * * * * * * * *
 
380
  * All claim-related functions should operate solely
381
  * on the primary store.
382
  * * * * * * * * * * * * * * * * * * * * * * * * * * */
53
  * @codeCoverageIgnore
54
  */
55
  public function init() {
56
+ add_action( 'action_scheduler/created_table', array( $this, 'set_autoincrement' ), 10, 2 );
57
  $this->primary_store->init();
58
  $this->secondary_store->init();
59
+ remove_action( 'action_scheduler/created_table', array( $this, 'set_autoincrement' ), 10 );
60
  }
61
 
62
  /**
78
  /** @var \wpdb $wpdb */
79
  global $wpdb;
80
  /**
81
+ * A default date of '0000-00-00 00:00:00' is invalid in MySQL 5.7 when configured with
82
  * sql_mode including both STRICT_TRANS_TABLES and NO_ZERO_DATE.
83
  */
84
  $default_date = new DateTime( 'tomorrow' );
88
 
89
  $row_count = $wpdb->insert(
90
  $wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
91
+ array(
92
  'action_id' => $this->demarkation_id,
93
  'hook' => '',
94
  'status' => '',
96
  'scheduled_date_local' => $date_local,
97
  'last_attempt_gmt' => $date_gmt,
98
  'last_attempt_local' => $date_local,
99
+ )
100
  );
101
  if ( $row_count > 0 ) {
102
  $wpdb->delete(
103
  $wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
104
+ array( 'action_id' => $this->demarkation_id )
105
  );
106
  }
107
  }
140
  *
141
  * @return string
142
  */
143
+ public function find_action( $hook, $params = array() ) {
144
  $found_unmigrated_action = $this->secondary_store->find_action( $hook, $params );
145
  if ( ! empty( $found_unmigrated_action ) ) {
146
+ $this->migrate( array( $found_unmigrated_action ) );
147
  }
148
 
149
  return $this->primary_store->find_action( $hook, $params );
154
  * If any are found, migrate them immediately. Then the secondary
155
  * store will contain the canonical results.
156
  *
157
+ * @param array $query
158
  * @param string $query_type Whether to select or count the results. Default, select.
159
  *
160
  * @return int[]
161
  */
162
+ public function query_actions( $query = array(), $query_type = 'select' ) {
163
  $found_unmigrated_actions = $this->secondary_store->query_actions( $query, 'select' );
164
  if ( ! empty( $found_unmigrated_actions ) ) {
165
  $this->migrate( $found_unmigrated_actions );
352
  */
353
  protected function get_store_from_action_id( $action_id, $primary_first = false ) {
354
  if ( $primary_first ) {
355
+ $stores = array(
356
  $this->primary_store,
357
  $this->secondary_store,
358
+ );
359
  } elseif ( $action_id < $this->demarkation_id ) {
360
+ $stores = array(
361
  $this->secondary_store,
362
  $this->primary_store,
363
+ );
364
  } else {
365
+ $stores = array(
366
  $this->primary_store,
367
+ );
368
  }
369
 
370
  foreach ( $stores as $store ) {
376
  return null;
377
  }
378
 
379
+ /*
380
+ * * * * * * * * * * * * * * * * * * * * * * * * * *
381
  * All claim-related functions should operate solely
382
  * on the primary store.
383
  * * * * * * * * * * * * * * * * * * * * * * * * * * */
lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_wpCommentLogger.php CHANGED
@@ -5,17 +5,17 @@
5
  */
6
  class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
7
  const AGENT = 'ActionScheduler';
8
- const TYPE = 'action_log';
9
 
10
  /**
11
- * @param string $action_id
12
- * @param string $message
13
  * @param DateTime $date
14
  *
15
  * @return string The log entry ID
16
  */
17
- public function log( $action_id, $message, DateTime $date = NULL ) {
18
- if ( empty($date) ) {
19
  $date = as_get_datetime_object();
20
  } else {
21
  $date = as_get_datetime_object( clone $date );
@@ -26,18 +26,18 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
26
 
27
  protected function create_wp_comment( $action_id, $message, DateTime $date ) {
28
 
29
- $comment_date_gmt = $date->format('Y-m-d H:i:s');
30
  ActionScheduler_TimezoneHelper::set_local_timezone( $date );
31
  $comment_data = array(
32
- 'comment_post_ID' => $action_id,
33
- 'comment_date' => $date->format('Y-m-d H:i:s'),
34
  'comment_date_gmt' => $comment_date_gmt,
35
- 'comment_author' => self::AGENT,
36
- 'comment_content' => $message,
37
- 'comment_agent' => self::AGENT,
38
- 'comment_type' => self::TYPE,
39
  );
40
- return wp_insert_comment($comment_data);
41
  }
42
 
43
  /**
@@ -47,7 +47,7 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
47
  */
48
  public function get_entry( $entry_id ) {
49
  $comment = $this->get_comment( $entry_id );
50
- if ( empty($comment) || $comment->comment_type != self::TYPE ) {
51
  return new ActionScheduler_NullLogEntry();
52
  }
53
 
@@ -63,20 +63,22 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
63
  */
64
  public function get_logs( $action_id ) {
65
  $status = 'all';
66
- if ( get_post_status($action_id) == 'trash' ) {
67
  $status = 'post-trashed';
68
  }
69
- $comments = get_comments(array(
70
- 'post_id' => $action_id,
71
- 'orderby' => 'comment_date_gmt',
72
- 'order' => 'ASC',
73
- 'type' => self::TYPE,
74
- 'status' => $status,
75
- ));
76
- $logs = array();
 
 
77
  foreach ( $comments as $c ) {
78
  $entry = $this->get_entry( $c );
79
- if ( !empty($entry) ) {
80
  $logs[] = $entry;
81
  }
82
  }
@@ -93,23 +95,23 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
93
  * @param WP_Comment_Query $query
94
  */
95
  public function filter_comment_queries( $query ) {
96
- foreach ( array('ID', 'parent', 'post_author', 'post_name', 'post_parent', 'type', 'post_type', 'post_id', 'post_ID') as $key ) {
97
- if ( !empty($query->query_vars[$key]) ) {
98
  return; // don't slow down queries that wouldn't include action_log comments anyway
99
  }
100
  }
101
- $query->query_vars['action_log_filter'] = TRUE;
102
  add_filter( 'comments_clauses', array( $this, 'filter_comment_query_clauses' ), 10, 2 );
103
  }
104
 
105
  /**
106
- * @param array $clauses
107
  * @param WP_Comment_Query $query
108
  *
109
  * @return array
110
  */
111
  public function filter_comment_query_clauses( $clauses, $query ) {
112
- if ( !empty($query->query_vars['action_log_filter']) ) {
113
  $clauses['where'] .= $this->get_where_clause();
114
  }
115
  return $clauses;
@@ -119,7 +121,7 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
119
  * Make sure Action Scheduler logs are excluded from comment feeds, which use WP_Query, not
120
  * the WP_Comment_Query class handled by @see self::filter_comment_queries().
121
  *
122
- * @param string $where
123
  * @param WP_Query $query
124
  *
125
  * @return string
@@ -145,7 +147,7 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
145
  * Remove action log entries from wp_count_comments()
146
  *
147
  * @param array $stats
148
- * @param int $post_id
149
  *
150
  * @return object
151
  */
@@ -174,9 +176,15 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
174
 
175
  $count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} WHERE comment_type NOT IN('order_note','action_log') GROUP BY comment_approved", ARRAY_A );
176
 
177
- $total = 0;
178
- $stats = array();
179
- $approved = array( '0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed' );
 
 
 
 
 
 
180
 
181
  foreach ( (array) $count as $row ) {
182
  // Don't count post-trashed toward totals
@@ -231,10 +239,10 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
231
  }
232
 
233
  public function disable_comment_counting() {
234
- wp_defer_comment_counting(true);
235
  }
236
  public function enable_comment_counting() {
237
- wp_defer_comment_counting(false);
238
  }
239
 
240
  }
5
  */
6
  class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
7
  const AGENT = 'ActionScheduler';
8
+ const TYPE = 'action_log';
9
 
10
  /**
11
+ * @param string $action_id
12
+ * @param string $message
13
  * @param DateTime $date
14
  *
15
  * @return string The log entry ID
16
  */
17
+ public function log( $action_id, $message, DateTime $date = null ) {
18
+ if ( empty( $date ) ) {
19
  $date = as_get_datetime_object();
20
  } else {
21
  $date = as_get_datetime_object( clone $date );
26
 
27
  protected function create_wp_comment( $action_id, $message, DateTime $date ) {
28
 
29
+ $comment_date_gmt = $date->format( 'Y-m-d H:i:s' );
30
  ActionScheduler_TimezoneHelper::set_local_timezone( $date );
31
  $comment_data = array(
32
+ 'comment_post_ID' => $action_id,
33
+ 'comment_date' => $date->format( 'Y-m-d H:i:s' ),
34
  'comment_date_gmt' => $comment_date_gmt,
35
+ 'comment_author' => self::AGENT,
36
+ 'comment_content' => $message,
37
+ 'comment_agent' => self::AGENT,
38
+ 'comment_type' => self::TYPE,
39
  );
40
+ return wp_insert_comment( $comment_data );
41
  }
42
 
43
  /**
47
  */
48
  public function get_entry( $entry_id ) {
49
  $comment = $this->get_comment( $entry_id );
50
+ if ( empty( $comment ) || $comment->comment_type != self::TYPE ) {
51
  return new ActionScheduler_NullLogEntry();
52
  }
53
 
63
  */
64
  public function get_logs( $action_id ) {
65
  $status = 'all';
66
+ if ( get_post_status( $action_id ) == 'trash' ) {
67
  $status = 'post-trashed';
68
  }
69
+ $comments = get_comments(
70
+ array(
71
+ 'post_id' => $action_id,
72
+ 'orderby' => 'comment_date_gmt',
73
+ 'order' => 'ASC',
74
+ 'type' => self::TYPE,
75
+ 'status' => $status,
76
+ )
77
+ );
78
+ $logs = array();
79
  foreach ( $comments as $c ) {
80
  $entry = $this->get_entry( $c );
81
+ if ( ! empty( $entry ) ) {
82
  $logs[] = $entry;
83
  }
84
  }
95
  * @param WP_Comment_Query $query
96
  */
97
  public function filter_comment_queries( $query ) {
98
+ foreach ( array( 'ID', 'parent', 'post_author', 'post_name', 'post_parent', 'type', 'post_type', 'post_id', 'post_ID' ) as $key ) {
99
+ if ( ! empty( $query->query_vars[ $key ] ) ) {
100
  return; // don't slow down queries that wouldn't include action_log comments anyway
101
  }
102
  }
103
+ $query->query_vars['action_log_filter'] = true;
104
  add_filter( 'comments_clauses', array( $this, 'filter_comment_query_clauses' ), 10, 2 );
105
  }
106
 
107
  /**
108
+ * @param array $clauses
109
  * @param WP_Comment_Query $query
110
  *
111
  * @return array
112
  */
113
  public function filter_comment_query_clauses( $clauses, $query ) {
114
+ if ( ! empty( $query->query_vars['action_log_filter'] ) ) {
115
  $clauses['where'] .= $this->get_where_clause();
116
  }
117
  return $clauses;
121
  * Make sure Action Scheduler logs are excluded from comment feeds, which use WP_Query, not
122
  * the WP_Comment_Query class handled by @see self::filter_comment_queries().
123
  *
124
+ * @param string $where
125
  * @param WP_Query $query
126
  *
127
  * @return string
147
  * Remove action log entries from wp_count_comments()
148
  *
149
  * @param array $stats
150
+ * @param int $post_id
151
  *
152
  * @return object
153
  */
176
 
177
  $count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} WHERE comment_type NOT IN('order_note','action_log') GROUP BY comment_approved", ARRAY_A );
178
 
179
+ $total = 0;
180
+ $stats = array();
181
+ $approved = array(
182
+ '0' => 'moderated',
183
+ '1' => 'approved',
184
+ 'spam' => 'spam',
185
+ 'trash' => 'trash',
186
+ 'post-trashed' => 'post-trashed',
187
+ );
188
 
189
  foreach ( (array) $count as $row ) {
190
  // Don't count post-trashed toward totals
239
  }
240
 
241
  public function disable_comment_counting() {
242
+ wp_defer_comment_counting( true );
243
  }
244
  public function enable_comment_counting() {
245
+ wp_defer_comment_counting( false );
246
  }
247
 
248
  }
lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php CHANGED
@@ -4,19 +4,19 @@
4
  * Class ActionScheduler_wpPostStore
5
  */
6
  class ActionScheduler_wpPostStore extends ActionScheduler_Store {
7
- const POST_TYPE = 'scheduled-action';
8
- const GROUP_TAXONOMY = 'action-group';
9
  const SCHEDULE_META_KEY = '_action_manager_schedule';
10
- const DEPENDENCIES_MET = 'as-post-store-dependencies-met';
11
 
12
  /** @var DateTimeZone */
13
- protected $local_timezone = NULL;
14
 
15
- public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ){
16
  try {
17
  $this->validate_action( $action );
18
  $post_array = $this->create_post_array( $action, $scheduled_date );
19
- $post_id = $this->save_post_array( $post_array );
20
  $this->save_post_schedule( $post_id, $action->get_schedule() );
21
  $this->save_action_group( $post_id, $action->get_group() );
22
  do_action( 'action_scheduler_stored_action', $post_id );
@@ -26,12 +26,12 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
26
  }
27
  }
28
 
29
- protected function create_post_array( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
30
  $post = array(
31
- 'post_type' => self::POST_TYPE,
32
- 'post_title' => $action->get_hook(),
33
- 'post_content' => json_encode($action->get_args()),
34
- 'post_status' => ( $action->is_finished() ? 'publish' : 'pending' ),
35
  'post_date_gmt' => $this->get_scheduled_date_string( $action, $scheduled_date ),
36
  'post_date' => $this->get_scheduled_date_string_local( $action, $scheduled_date ),
37
  );
@@ -49,7 +49,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
49
  kses_remove_filters();
50
  }
51
 
52
- $post_id = wp_insert_post($post_array);
53
 
54
  if ( $has_kses ) {
55
  kses_init_filters();
@@ -58,7 +58,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
58
  remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
59
  remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
60
 
61
- if ( is_wp_error($post_id) || empty($post_id) ) {
62
  throw new RuntimeException( __( 'Unable to save action.', 'action-scheduler' ) );
63
  }
64
  return $post_id;
@@ -114,16 +114,16 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
114
  }
115
 
116
  protected function save_action_group( $post_id, $group ) {
117
- if ( empty($group) ) {
118
- wp_set_object_terms( $post_id, array(), self::GROUP_TAXONOMY, FALSE );
119
  } else {
120
- wp_set_object_terms( $post_id, array($group), self::GROUP_TAXONOMY, FALSE );
121
  }
122
  }
123
 
124
  public function fetch_action( $action_id ) {
125
  $post = $this->get_post( $action_id );
126
- if ( empty($post) || $post->post_type != self::POST_TYPE ) {
127
  return $this->get_null_action();
128
  }
129
 
@@ -138,10 +138,10 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
138
  }
139
 
140
  protected function get_post( $action_id ) {
141
- if ( empty($action_id) ) {
142
- return NULL;
143
  }
144
- return get_post($action_id);
145
  }
146
 
147
  protected function get_null_action() {
@@ -157,8 +157,8 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
157
  $schedule = get_post_meta( $post->ID, self::SCHEDULE_META_KEY, true );
158
  $this->validate_schedule( $schedule, $post->ID );
159
 
160
- $group = wp_get_object_terms( $post->ID, self::GROUP_TAXONOMY, array('fields' => 'names') );
161
- $group = empty( $group ) ? '' : reset($group);
162
 
163
  return ActionScheduler::factory()->get_stored_action( $this->get_action_status_by_post_status( $post->post_status ), $hook, $args, $schedule, $group );
164
  }
@@ -172,13 +172,13 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
172
  protected function get_action_status_by_post_status( $post_status ) {
173
 
174
  switch ( $post_status ) {
175
- case 'publish' :
176
  $action_status = self::STATUS_COMPLETE;
177
  break;
178
- case 'trash' :
179
  $action_status = self::STATUS_CANCELED;
180
  break;
181
- default :
182
  if ( ! array_key_exists( $post_status, $this->get_status_labels() ) ) {
183
  throw new InvalidArgumentException( sprintf( 'Invalid post status: "%s". No matching action status available.', $post_status ) );
184
  }
@@ -197,13 +197,13 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
197
  protected function get_post_status_by_action_status( $action_status ) {
198
 
199
  switch ( $action_status ) {
200
- case self::STATUS_COMPLETE :
201
  $post_status = 'publish';
202
  break;
203
- case self::STATUS_CANCELED :
204
  $post_status = 'trash';
205
  break;
206
- default :
207
  if ( ! array_key_exists( $action_status, $this->get_status_labels() ) ) {
208
  throw new InvalidArgumentException( sprintf( 'Invalid action status: "%s".', $action_status ) );
209
  }
@@ -216,37 +216,40 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
216
 
217
  /**
218
  * @param string $hook
219
- * @param array $params
220
  *
221
  * @return string ID of the next action matching the criteria or NULL if not found
222
  */
223
  public function find_action( $hook, $params = array() ) {
224
- $params = wp_parse_args( $params, array(
225
- 'args' => NULL,
226
- 'status' => ActionScheduler_Store::STATUS_PENDING,
227
- 'group' => '',
228
- ));
 
 
 
229
  /** @var wpdb $wpdb */
230
  global $wpdb;
231
  $query = "SELECT p.ID FROM {$wpdb->posts} p";
232
- $args = array();
233
- if ( !empty($params['group']) ) {
234
  $query .= " INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
235
  $query .= " INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
236
  $query .= " INNER JOIN {$wpdb->terms} t ON tt.term_id=t.term_id AND t.slug=%s";
237
  $args[] = $params['group'];
238
  }
239
- $query .= " WHERE p.post_title=%s";
240
  $args[] = $hook;
241
- $query .= " AND p.post_type=%s";
242
  $args[] = self::POST_TYPE;
243
- if ( !is_null($params['args']) ) {
244
- $query .= " AND p.post_content=%s";
245
- $args[] = json_encode($params['args']);
246
  }
247
 
248
  if ( ! empty( $params['status'] ) ) {
249
- $query .= " AND p.post_status=%s";
250
  $args[] = $this->get_post_status_by_action_status( $params['status'] );
251
  }
252
 
@@ -265,14 +268,14 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
265
 
266
  $query = $wpdb->prepare( $query, $args );
267
 
268
- $id = $wpdb->get_var($query);
269
  return $id;
270
  }
271
 
272
  /**
273
  * Returns the SQL statement to query (or count) actions.
274
  *
275
- * @param array $query Filtering options
276
  * @param string $select_or_count Whether the SQL should select and return the IDs or just the row count
277
  * @throws InvalidArgumentException if $select_or_count not count or select
278
  * @return string SQL statement. The returned SQL is already properly escaped.
@@ -283,85 +286,88 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
283
  throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'action-scheduler' ) );
284
  }
285
 
286
- $query = wp_parse_args( $query, array(
287
- 'hook' => '',
288
- 'args' => NULL,
289
- 'date' => NULL,
290
- 'date_compare' => '<=',
291
- 'modified' => NULL,
292
- 'modified_compare' => '<=',
293
- 'group' => '',
294
- 'status' => '',
295
- 'claimed' => NULL,
296
- 'per_page' => 5,
297
- 'offset' => 0,
298
- 'orderby' => 'date',
299
- 'order' => 'ASC',
300
- 'search' => '',
301
- ) );
 
 
 
302
 
303
  /** @var wpdb $wpdb */
304
  global $wpdb;
305
- $sql = ( 'count' === $select_or_count ) ? 'SELECT count(p.ID)' : 'SELECT p.ID ';
306
- $sql .= "FROM {$wpdb->posts} p";
307
  $sql_params = array();
308
  if ( empty( $query['group'] ) && 'group' === $query['orderby'] ) {
309
  $sql .= " LEFT JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
310
  $sql .= " LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
311
  $sql .= " LEFT JOIN {$wpdb->terms} t ON tt.term_id=t.term_id";
312
  } elseif ( ! empty( $query['group'] ) ) {
313
- $sql .= " INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
314
- $sql .= " INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
315
- $sql .= " INNER JOIN {$wpdb->terms} t ON tt.term_id=t.term_id";
316
- $sql .= " AND t.slug=%s";
317
  $sql_params[] = $query['group'];
318
  }
319
- $sql .= " WHERE post_type=%s";
320
  $sql_params[] = self::POST_TYPE;
321
  if ( $query['hook'] ) {
322
- $sql .= " AND p.post_title=%s";
323
  $sql_params[] = $query['hook'];
324
  }
325
- if ( !is_null($query['args']) ) {
326
- $sql .= " AND p.post_content=%s";
327
- $sql_params[] = json_encode($query['args']);
328
  }
329
 
330
  if ( ! empty( $query['status'] ) ) {
331
- $sql .= " AND p.post_status=%s";
332
  $sql_params[] = $this->get_post_status_by_action_status( $query['status'] );
333
  }
334
 
335
  if ( $query['date'] instanceof DateTime ) {
336
  $date = clone $query['date'];
337
- $date->setTimezone( new DateTimeZone('UTC') );
338
- $date_string = $date->format('Y-m-d H:i:s');
339
- $comparator = $this->validate_sql_comparator($query['date_compare']);
340
- $sql .= " AND p.post_date_gmt $comparator %s";
341
  $sql_params[] = $date_string;
342
  }
343
 
344
  if ( $query['modified'] instanceof DateTime ) {
345
  $modified = clone $query['modified'];
346
- $modified->setTimezone( new DateTimeZone('UTC') );
347
- $date_string = $modified->format('Y-m-d H:i:s');
348
- $comparator = $this->validate_sql_comparator($query['modified_compare']);
349
- $sql .= " AND p.post_modified_gmt $comparator %s";
350
  $sql_params[] = $date_string;
351
  }
352
 
353
- if ( $query['claimed'] === TRUE ) {
354
  $sql .= " AND p.post_password != ''";
355
- } elseif ( $query['claimed'] === FALSE ) {
356
  $sql .= " AND p.post_password = ''";
357
- } elseif ( !is_null($query['claimed']) ) {
358
- $sql .= " AND p.post_password = %s";
359
  $sql_params[] = $query['claimed'];
360
  }
361
 
362
  if ( ! empty( $query['search'] ) ) {
363
- $sql .= " AND (p.post_title LIKE %s OR p.post_content LIKE %s OR p.post_password LIKE %s)";
364
- for( $i = 0; $i < 3; $i++ ) {
365
  $sql_params[] = sprintf( '%%%s%%', $query['search'] );
366
  }
367
  }
@@ -396,7 +402,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
396
  }
397
  $sql .= " ORDER BY $orderby $order";
398
  if ( $query['per_page'] > 0 ) {
399
- $sql .= " LIMIT %d, %d";
400
  $sql_params[] = $query['offset'];
401
  $sql_params[] = $query['per_page'];
402
  }
@@ -406,7 +412,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
406
  }
407
 
408
  /**
409
- * @param array $query
410
  * @param string $query_type Whether to select or count the results. Default, select.
411
  * @return string|array The IDs of actions matching the query
412
  */
@@ -469,7 +475,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
469
  }
470
  do_action( 'action_scheduler_deleted_action', $action_id );
471
 
472
- wp_delete_post( $action_id, TRUE );
473
  }
474
 
475
  /**
@@ -522,7 +528,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
522
  /**
523
  * @return int
524
  */
525
- public function get_claim_count(){
526
  global $wpdb;
527
 
528
  $sql = "SELECT COUNT(DISTINCT post_password) FROM {$wpdb->posts} WHERE post_password != '' AND post_type = %s AND post_status IN ('in-progress','pending')";
@@ -532,8 +538,8 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
532
  }
533
 
534
  protected function generate_claim_id() {
535
- $claim_id = md5(microtime(true) . rand(0,1000));
536
- return substr($claim_id, 0, 20); // to fit in db field with 20 char limit
537
  }
538
 
539
  /**
@@ -593,7 +599,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
593
  if ( $limit_ids ) {
594
  $where .= ' AND ID IN (' . join( ',', $ids ) . ')';
595
  } else {
596
- $where .= ' AND post_date_gmt <= %s';
597
  $params[] = $date->format( 'Y-m-d H:i:s' );
598
  }
599
 
@@ -623,7 +629,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
623
  */
624
  protected function get_actions_by_group( $group, $limit, DateTime $date ) {
625
  // Ensure the group exists before continuing.
626
- if ( ! term_exists( $group, self::GROUP_TAXONOMY )) {
627
  throw new InvalidArgumentException( sprintf( __( 'The group "%s" does not exist.', 'action-scheduler' ), $group ) );
628
  }
629
 
@@ -643,11 +649,11 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
643
  'ID' => 'ASC',
644
  ),
645
  'date_query' => array(
646
- 'column' => 'post_date_gmt',
647
- 'before' => $date->format( 'Y-m-d H:i' ),
648
  'inclusive' => true,
649
  ),
650
- 'tax_query' => array(
651
  array(
652
  'taxonomy' => self::GROUP_TAXONOMY,
653
  'field' => 'slug',
@@ -667,8 +673,8 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
667
  public function find_actions_by_claim_id( $claim_id ) {
668
  /** @var wpdb $wpdb */
669
  global $wpdb;
670
- $sql = "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_password = %s";
671
- $sql = $wpdb->prepare( $sql, array( self::POST_TYPE, $claim_id ) );
672
  $action_ids = $wpdb->get_col( $sql );
673
  return $action_ids;
674
  }
@@ -681,8 +687,8 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
681
  $action_id_string = implode( ',', array_map( 'intval', $action_ids ) );
682
  /** @var wpdb $wpdb */
683
  global $wpdb;
684
- $sql = "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID IN ($action_id_string) AND post_password = %s";
685
- $sql = $wpdb->prepare( $sql, array( $claim->get_id() ) );
686
  $result = $wpdb->query( $sql );
687
  if ( $result === false ) {
688
  /* translators: %s: claim ID */
@@ -696,8 +702,8 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
696
  public function unclaim_action( $action_id ) {
697
  /** @var wpdb $wpdb */
698
  global $wpdb;
699
- $sql = "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID = %d AND post_type = %s";
700
- $sql = $wpdb->prepare( $sql, $action_id, self::POST_TYPE );
701
  $result = $wpdb->query( $sql );
702
  if ( $result === false ) {
703
  /* translators: %s: action ID */
@@ -708,8 +714,8 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
708
  public function mark_failure( $action_id ) {
709
  /** @var wpdb $wpdb */
710
  global $wpdb;
711
- $sql = "UPDATE {$wpdb->posts} SET post_status = %s WHERE ID = %d AND post_type = %s";
712
- $sql = $wpdb->prepare( $sql, self::STATUS_FAILED, $action_id, self::POST_TYPE );
713
  $result = $wpdb->query( $sql );
714
  if ( $result === false ) {
715
  /* translators: %s: action ID */
@@ -757,8 +763,8 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
757
  global $wpdb;
758
 
759
  $sql = "UPDATE {$wpdb->posts} SET menu_order = menu_order+1, post_status=%s, post_modified_gmt = %s, post_modified = %s WHERE ID = %d AND post_type = %s";
760
- $sql = $wpdb->prepare( $sql, self::STATUS_RUNNING, current_time('mysql', true), current_time('mysql'), $action_id, self::POST_TYPE );
761
- $wpdb->query($sql);
762
  }
763
 
764
  /**
@@ -774,10 +780,13 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
774
  }
775
  add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
776
  add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
777
- $result = wp_update_post(array(
778
- 'ID' => $action_id,
779
- 'post_status' => 'publish',
780
- ), TRUE);
 
 
 
781
  remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
782
  remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
783
  if ( is_wp_error( $result ) ) {
@@ -794,7 +803,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
794
  wp_update_post(
795
  array(
796
  'ID' => $action_id,
797
- 'post_status' => 'migrated'
798
  )
799
  );
800
  }
@@ -817,7 +826,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
817
  self::POST_TYPE
818
  )
819
  );
820
- $dependencies_met = $found_action ? 'no' : 'yes';
821
  set_transient( self::DEPENDENCIES_MET, $dependencies_met, DAY_IN_SECONDS );
822
  }
823
 
4
  * Class ActionScheduler_wpPostStore
5
  */
6
  class ActionScheduler_wpPostStore extends ActionScheduler_Store {
7
+ const POST_TYPE = 'scheduled-action';
8
+ const GROUP_TAXONOMY = 'action-group';
9
  const SCHEDULE_META_KEY = '_action_manager_schedule';
10
+ const DEPENDENCIES_MET = 'as-post-store-dependencies-met';
11
 
12
  /** @var DateTimeZone */
13
+ protected $local_timezone = null;
14
 
15
+ public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = null ) {
16
  try {
17
  $this->validate_action( $action );
18
  $post_array = $this->create_post_array( $action, $scheduled_date );
19
+ $post_id = $this->save_post_array( $post_array );
20
  $this->save_post_schedule( $post_id, $action->get_schedule() );
21
  $this->save_action_group( $post_id, $action->get_group() );
22
  do_action( 'action_scheduler_stored_action', $post_id );
26
  }
27
  }
28
 
29
+ protected function create_post_array( ActionScheduler_Action $action, DateTime $scheduled_date = null ) {
30
  $post = array(
31
+ 'post_type' => self::POST_TYPE,
32
+ 'post_title' => $action->get_hook(),
33
+ 'post_content' => json_encode( $action->get_args() ),
34
+ 'post_status' => ( $action->is_finished() ? 'publish' : 'pending' ),
35
  'post_date_gmt' => $this->get_scheduled_date_string( $action, $scheduled_date ),
36
  'post_date' => $this->get_scheduled_date_string_local( $action, $scheduled_date ),
37
  );
49
  kses_remove_filters();
50
  }
51
 
52
+ $post_id = wp_insert_post( $post_array );
53
 
54
  if ( $has_kses ) {
55
  kses_init_filters();
58
  remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
59
  remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
60
 
61
+ if ( is_wp_error( $post_id ) || empty( $post_id ) ) {
62
  throw new RuntimeException( __( 'Unable to save action.', 'action-scheduler' ) );
63
  }
64
  return $post_id;
114
  }
115
 
116
  protected function save_action_group( $post_id, $group ) {
117
+ if ( empty( $group ) ) {
118
+ wp_set_object_terms( $post_id, array(), self::GROUP_TAXONOMY, false );
119
  } else {
120
+ wp_set_object_terms( $post_id, array( $group ), self::GROUP_TAXONOMY, false );
121
  }
122
  }
123
 
124
  public function fetch_action( $action_id ) {
125
  $post = $this->get_post( $action_id );
126
+ if ( empty( $post ) || $post->post_type != self::POST_TYPE ) {
127
  return $this->get_null_action();
128
  }
129
 
138
  }
139
 
140
  protected function get_post( $action_id ) {
141
+ if ( empty( $action_id ) ) {
142
+ return null;
143
  }
144
+ return get_post( $action_id );
145
  }
146
 
147
  protected function get_null_action() {
157
  $schedule = get_post_meta( $post->ID, self::SCHEDULE_META_KEY, true );
158
  $this->validate_schedule( $schedule, $post->ID );
159
 
160
+ $group = wp_get_object_terms( $post->ID, self::GROUP_TAXONOMY, array( 'fields' => 'names' ) );
161
+ $group = empty( $group ) ? '' : reset( $group );
162
 
163
  return ActionScheduler::factory()->get_stored_action( $this->get_action_status_by_post_status( $post->post_status ), $hook, $args, $schedule, $group );
164
  }
172
  protected function get_action_status_by_post_status( $post_status ) {
173
 
174
  switch ( $post_status ) {
175
+ case 'publish':
176
  $action_status = self::STATUS_COMPLETE;
177
  break;
178
+ case 'trash':
179
  $action_status = self::STATUS_CANCELED;
180
  break;
181
+ default:
182
  if ( ! array_key_exists( $post_status, $this->get_status_labels() ) ) {
183
  throw new InvalidArgumentException( sprintf( 'Invalid post status: "%s". No matching action status available.', $post_status ) );
184
  }
197
  protected function get_post_status_by_action_status( $action_status ) {
198
 
199
  switch ( $action_status ) {
200
+ case self::STATUS_COMPLETE:
201
  $post_status = 'publish';
202
  break;
203
+ case self::STATUS_CANCELED:
204
  $post_status = 'trash';
205
  break;
206
+ default:
207
  if ( ! array_key_exists( $action_status, $this->get_status_labels() ) ) {
208
  throw new InvalidArgumentException( sprintf( 'Invalid action status: "%s".', $action_status ) );
209
  }
216
 
217
  /**
218
  * @param string $hook
219
+ * @param array $params
220
  *
221
  * @return string ID of the next action matching the criteria or NULL if not found
222
  */
223
  public function find_action( $hook, $params = array() ) {
224
+ $params = wp_parse_args(
225
+ $params,
226
+ array(
227
+ 'args' => null,
228
+ 'status' => ActionScheduler_Store::STATUS_PENDING,
229
+ 'group' => '',
230
+ )
231
+ );
232
  /** @var wpdb $wpdb */
233
  global $wpdb;
234
  $query = "SELECT p.ID FROM {$wpdb->posts} p";
235
+ $args = array();
236
+ if ( ! empty( $params['group'] ) ) {
237
  $query .= " INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
238
  $query .= " INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
239
  $query .= " INNER JOIN {$wpdb->terms} t ON tt.term_id=t.term_id AND t.slug=%s";
240
  $args[] = $params['group'];
241
  }
242
+ $query .= ' WHERE p.post_title=%s';
243
  $args[] = $hook;
244
+ $query .= ' AND p.post_type=%s';
245
  $args[] = self::POST_TYPE;
246
+ if ( ! is_null( $params['args'] ) ) {
247
+ $query .= ' AND p.post_content=%s';
248
+ $args[] = json_encode( $params['args'] );
249
  }
250
 
251
  if ( ! empty( $params['status'] ) ) {
252
+ $query .= ' AND p.post_status=%s';
253
  $args[] = $this->get_post_status_by_action_status( $params['status'] );
254
  }
255
 
268
 
269
  $query = $wpdb->prepare( $query, $args );
270
 
271
+ $id = $wpdb->get_var( $query );
272
  return $id;
273
  }
274
 
275
  /**
276
  * Returns the SQL statement to query (or count) actions.
277
  *
278
+ * @param array $query Filtering options
279
  * @param string $select_or_count Whether the SQL should select and return the IDs or just the row count
280
  * @throws InvalidArgumentException if $select_or_count not count or select
281
  * @return string SQL statement. The returned SQL is already properly escaped.
286
  throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'action-scheduler' ) );
287
  }
288
 
289
+ $query = wp_parse_args(
290
+ $query,
291
+ array(
292
+ 'hook' => '',
293
+ 'args' => null,
294
+ 'date' => null,
295
+ 'date_compare' => '<=',
296
+ 'modified' => null,
297
+ 'modified_compare' => '<=',
298
+ 'group' => '',
299
+ 'status' => '',
300
+ 'claimed' => null,
301
+ 'per_page' => 5,
302
+ 'offset' => 0,
303
+ 'orderby' => 'date',
304
+ 'order' => 'ASC',
305
+ 'search' => '',
306
+ )
307
+ );
308
 
309
  /** @var wpdb $wpdb */
310
  global $wpdb;
311
+ $sql = ( 'count' === $select_or_count ) ? 'SELECT count(p.ID)' : 'SELECT p.ID ';
312
+ $sql .= "FROM {$wpdb->posts} p";
313
  $sql_params = array();
314
  if ( empty( $query['group'] ) && 'group' === $query['orderby'] ) {
315
  $sql .= " LEFT JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
316
  $sql .= " LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
317
  $sql .= " LEFT JOIN {$wpdb->terms} t ON tt.term_id=t.term_id";
318
  } elseif ( ! empty( $query['group'] ) ) {
319
+ $sql .= " INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
320
+ $sql .= " INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
321
+ $sql .= " INNER JOIN {$wpdb->terms} t ON tt.term_id=t.term_id";
322
+ $sql .= ' AND t.slug=%s';
323
  $sql_params[] = $query['group'];
324
  }
325
+ $sql .= ' WHERE post_type=%s';
326
  $sql_params[] = self::POST_TYPE;
327
  if ( $query['hook'] ) {
328
+ $sql .= ' AND p.post_title=%s';
329
  $sql_params[] = $query['hook'];
330
  }
331
+ if ( ! is_null( $query['args'] ) ) {
332
+ $sql .= ' AND p.post_content=%s';
333
+ $sql_params[] = json_encode( $query['args'] );
334
  }
335
 
336
  if ( ! empty( $query['status'] ) ) {
337
+ $sql .= ' AND p.post_status=%s';
338
  $sql_params[] = $this->get_post_status_by_action_status( $query['status'] );
339
  }
340
 
341
  if ( $query['date'] instanceof DateTime ) {
342
  $date = clone $query['date'];
343
+ $date->setTimezone( new DateTimeZone( 'UTC' ) );
344
+ $date_string = $date->format( 'Y-m-d H:i:s' );
345
+ $comparator = $this->validate_sql_comparator( $query['date_compare'] );
346
+ $sql .= " AND p.post_date_gmt $comparator %s";
347
  $sql_params[] = $date_string;
348
  }
349
 
350
  if ( $query['modified'] instanceof DateTime ) {
351
  $modified = clone $query['modified'];
352
+ $modified->setTimezone( new DateTimeZone( 'UTC' ) );
353
+ $date_string = $modified->format( 'Y-m-d H:i:s' );
354
+ $comparator = $this->validate_sql_comparator( $query['modified_compare'] );
355
+ $sql .= " AND p.post_modified_gmt $comparator %s";
356
  $sql_params[] = $date_string;
357
  }
358
 
359
+ if ( $query['claimed'] === true ) {
360
  $sql .= " AND p.post_password != ''";
361
+ } elseif ( $query['claimed'] === false ) {
362
  $sql .= " AND p.post_password = ''";
363
+ } elseif ( ! is_null( $query['claimed'] ) ) {
364
+ $sql .= ' AND p.post_password = %s';
365
  $sql_params[] = $query['claimed'];
366
  }
367
 
368
  if ( ! empty( $query['search'] ) ) {
369
+ $sql .= ' AND (p.post_title LIKE %s OR p.post_content LIKE %s OR p.post_password LIKE %s)';
370
+ for ( $i = 0; $i < 3; $i++ ) {
371
  $sql_params[] = sprintf( '%%%s%%', $query['search'] );
372
  }
373
  }
402
  }
403
  $sql .= " ORDER BY $orderby $order";
404
  if ( $query['per_page'] > 0 ) {
405
+ $sql .= ' LIMIT %d, %d';
406
  $sql_params[] = $query['offset'];
407
  $sql_params[] = $query['per_page'];
408
  }
412
  }
413
 
414
  /**
415
+ * @param array $query
416
  * @param string $query_type Whether to select or count the results. Default, select.
417
  * @return string|array The IDs of actions matching the query
418
  */
475
  }
476
  do_action( 'action_scheduler_deleted_action', $action_id );
477
 
478
+ wp_delete_post( $action_id, true );
479
  }
480
 
481
  /**
528
  /**
529
  * @return int
530
  */
531
+ public function get_claim_count() {
532
  global $wpdb;
533
 
534
  $sql = "SELECT COUNT(DISTINCT post_password) FROM {$wpdb->posts} WHERE post_password != '' AND post_type = %s AND post_status IN ('in-progress','pending')";
538
  }
539
 
540
  protected function generate_claim_id() {
541
+ $claim_id = md5( microtime( true ) . rand( 0, 1000 ) );
542
+ return substr( $claim_id, 0, 20 ); // to fit in db field with 20 char limit
543
  }
544
 
545
  /**
599
  if ( $limit_ids ) {
600
  $where .= ' AND ID IN (' . join( ',', $ids ) . ')';
601
  } else {
602
+ $where .= ' AND post_date_gmt <= %s';
603
  $params[] = $date->format( 'Y-m-d H:i:s' );
604
  }
605
 
629
  */
630
  protected function get_actions_by_group( $group, $limit, DateTime $date ) {
631
  // Ensure the group exists before continuing.
632
+ if ( ! term_exists( $group, self::GROUP_TAXONOMY ) ) {
633
  throw new InvalidArgumentException( sprintf( __( 'The group "%s" does not exist.', 'action-scheduler' ), $group ) );
634
  }
635
 
649
  'ID' => 'ASC',
650
  ),
651
  'date_query' => array(
652
+ 'column' => 'post_date_gmt',
653
+ 'before' => $date->format( 'Y-m-d H:i' ),
654
  'inclusive' => true,
655
  ),
656
+ 'tax_query' => array(
657
  array(
658
  'taxonomy' => self::GROUP_TAXONOMY,
659
  'field' => 'slug',
673
  public function find_actions_by_claim_id( $claim_id ) {
674
  /** @var wpdb $wpdb */
675
  global $wpdb;
676
+ $sql = "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_password = %s";
677
+ $sql = $wpdb->prepare( $sql, array( self::POST_TYPE, $claim_id ) );
678
  $action_ids = $wpdb->get_col( $sql );
679
  return $action_ids;
680
  }
687
  $action_id_string = implode( ',', array_map( 'intval', $action_ids ) );
688
  /** @var wpdb $wpdb */
689
  global $wpdb;
690
+ $sql = "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID IN ($action_id_string) AND post_password = %s";
691
+ $sql = $wpdb->prepare( $sql, array( $claim->get_id() ) );
692
  $result = $wpdb->query( $sql );
693
  if ( $result === false ) {
694
  /* translators: %s: claim ID */
702
  public function unclaim_action( $action_id ) {
703
  /** @var wpdb $wpdb */
704
  global $wpdb;
705
+ $sql = "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID = %d AND post_type = %s";
706
+ $sql = $wpdb->prepare( $sql, $action_id, self::POST_TYPE );
707
  $result = $wpdb->query( $sql );
708
  if ( $result === false ) {
709
  /* translators: %s: action ID */
714
  public function mark_failure( $action_id ) {
715
  /** @var wpdb $wpdb */
716
  global $wpdb;
717
+ $sql = "UPDATE {$wpdb->posts} SET post_status = %s WHERE ID = %d AND post_type = %s";
718
+ $sql = $wpdb->prepare( $sql, self::STATUS_FAILED, $action_id, self::POST_TYPE );
719
  $result = $wpdb->query( $sql );
720
  if ( $result === false ) {
721
  /* translators: %s: action ID */
763
  global $wpdb;
764
 
765
  $sql = "UPDATE {$wpdb->posts} SET menu_order = menu_order+1, post_status=%s, post_modified_gmt = %s, post_modified = %s WHERE ID = %d AND post_type = %s";
766
+ $sql = $wpdb->prepare( $sql, self::STATUS_RUNNING, current_time( 'mysql', true ), current_time( 'mysql' ), $action_id, self::POST_TYPE );
767
+ $wpdb->query( $sql );
768
  }
769
 
770
  /**
780
  }
781
  add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
782
  add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
783
+ $result = wp_update_post(
784
+ array(
785
+ 'ID' => $action_id,
786
+ 'post_status' => 'publish',
787
+ ),
788
+ true
789
+ );
790
  remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
791
  remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
792
  if ( is_wp_error( $result ) ) {
803
  wp_update_post(
804
  array(
805
  'ID' => $action_id,
806
+ 'post_status' => 'migrated',
807
  )
808
  );
809
  }
826
  self::POST_TYPE
827
  )
828
  );
829
+ $dependencies_met = $found_action ? 'no' : 'yes';
830
  set_transient( self::DEPENDENCIES_MET, $dependencies_met, DAY_IN_SECONDS );
831
  }
832
 
lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostStatusRegistrar.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  /**
4
  * Class ActionScheduler_wpPostStore_PostStatusRegistrar
 
5
  * @codeCoverageIgnore
6
  */
7
  class ActionScheduler_wpPostStore_PostStatusRegistrar {
2
 
3
  /**
4
  * Class ActionScheduler_wpPostStore_PostStatusRegistrar
5
+ *
6
  * @codeCoverageIgnore
7
  */
8
  class ActionScheduler_wpPostStore_PostStatusRegistrar {
lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  /**
4
  * Class ActionScheduler_wpPostStore_PostTypeRegistrar
 
5
  * @codeCoverageIgnore
6
  */
7
  class ActionScheduler_wpPostStore_PostTypeRegistrar {
@@ -16,35 +17,35 @@ class ActionScheduler_wpPostStore_PostTypeRegistrar {
16
  */
17
  protected function post_type_args() {
18
  $args = array(
19
- 'label' => __( 'Scheduled Actions', 'action-scheduler' ),
20
- 'description' => __( 'Scheduled actions are hooks triggered on a cetain date and time.', 'action-scheduler' ),
21
- 'public' => false,
22
  'map_meta_cap' => true,
23
  'hierarchical' => false,
24
- 'supports' => array('title', 'editor','comments'),
25
- 'rewrite' => false,
26
- 'query_var' => false,
27
- 'can_export' => true,
28
- 'ep_mask' => EP_NONE,
29
- 'labels' => array(
30
- 'name' => __( 'Scheduled Actions', 'action-scheduler' ),
31
- 'singular_name' => __( 'Scheduled Action', 'action-scheduler' ),
32
- 'menu_name' => _x( 'Scheduled Actions', 'Admin menu name', 'action-scheduler' ),
33
- 'add_new' => __( 'Add', 'action-scheduler' ),
34
- 'add_new_item' => __( 'Add New Scheduled Action', 'action-scheduler' ),
35
- 'edit' => __( 'Edit', 'action-scheduler' ),
36
- 'edit_item' => __( 'Edit Scheduled Action', 'action-scheduler' ),
37
- 'new_item' => __( 'New Scheduled Action', 'action-scheduler' ),
38
- 'view' => __( 'View Action', 'action-scheduler' ),
39
- 'view_item' => __( 'View Action', 'action-scheduler' ),
40
- 'search_items' => __( 'Search Scheduled Actions', 'action-scheduler' ),
41
- 'not_found' => __( 'No actions found', 'action-scheduler' ),
42
  'not_found_in_trash' => __( 'No actions found in trash', 'action-scheduler' ),
43
  ),
44
  );
45
 
46
- $args = apply_filters('action_scheduler_post_type_args', $args);
47
  return $args;
48
  }
49
  }
50
-
2
 
3
  /**
4
  * Class ActionScheduler_wpPostStore_PostTypeRegistrar
5
+ *
6
  * @codeCoverageIgnore
7
  */
8
  class ActionScheduler_wpPostStore_PostTypeRegistrar {
17
  */
18
  protected function post_type_args() {
19
  $args = array(
20
+ 'label' => __( 'Scheduled Actions', 'action-scheduler' ),
21
+ 'description' => __( 'Scheduled actions are hooks triggered on a cetain date and time.', 'action-scheduler' ),
22
+ 'public' => false,
23
  'map_meta_cap' => true,
24
  'hierarchical' => false,
25
+ 'supports' => array( 'title', 'editor', 'comments' ),
26
+ 'rewrite' => false,
27
+ 'query_var' => false,
28
+ 'can_export' => true,
29
+ 'ep_mask' => EP_NONE,
30
+ 'labels' => array(
31
+ 'name' => __( 'Scheduled Actions', 'action-scheduler' ),
32
+ 'singular_name' => __( 'Scheduled Action', 'action-scheduler' ),
33
+ 'menu_name' => _x( 'Scheduled Actions', 'Admin menu name', 'action-scheduler' ),
34
+ 'add_new' => __( 'Add', 'action-scheduler' ),
35
+ 'add_new_item' => __( 'Add New Scheduled Action', 'action-scheduler' ),
36
+ 'edit' => __( 'Edit', 'action-scheduler' ),
37
+ 'edit_item' => __( 'Edit Scheduled Action', 'action-scheduler' ),
38
+ 'new_item' => __( 'New Scheduled Action', 'action-scheduler' ),
39
+ 'view' => __( 'View Action', 'action-scheduler' ),
40
+ 'view_item' => __( 'View Action', 'action-scheduler' ),
41
+ 'search_items' => __( 'Search Scheduled Actions', 'action-scheduler' ),
42
+ 'not_found' => __( 'No actions found', 'action-scheduler' ),
43
  'not_found_in_trash' => __( 'No actions found in trash', 'action-scheduler' ),
44
  ),
45
  );
46
 
47
+ $args = apply_filters( 'action_scheduler_post_type_args', $args );
48
  return $args;
49
  }
50
  }
51
+
lite/includes/libraries/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_TaxonomyRegistrar.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  /**
4
  * Class ActionScheduler_wpPostStore_TaxonomyRegistrar
 
5
  * @codeCoverageIgnore
6
  */
7
  class ActionScheduler_wpPostStore_TaxonomyRegistrar {
@@ -11,16 +12,16 @@ class ActionScheduler_wpPostStore_TaxonomyRegistrar {
11
 
12
  protected function taxonomy_args() {
13
  $args = array(
14
- 'label' => __( 'Action Group', 'action-scheduler' ),
15
- 'public' => false,
16
- 'hierarchical' => false,
17
  'show_admin_column' => true,
18
- 'query_var' => false,
19
- 'rewrite' => false,
20
  );
21
 
22
  $args = apply_filters( 'action_scheduler_taxonomy_args', $args );
23
  return $args;
24
  }
25
  }
26
-
2
 
3
  /**
4
  * Class ActionScheduler_wpPostStore_TaxonomyRegistrar
5
+ *
6
  * @codeCoverageIgnore
7
  */
8
  class ActionScheduler_wpPostStore_TaxonomyRegistrar {
12
 
13
  protected function taxonomy_args() {
14
  $args = array(
15
+ 'label' => __( 'Action Group', 'action-scheduler' ),
16
+ 'public' => false,
17
+ 'hierarchical' => false,
18
  'show_admin_column' => true,
19
+ 'query_var' => false,
20
+ 'rewrite' => false,
21
  );
22
 
23
  $args = apply_filters( 'action_scheduler_taxonomy_args', $args );
24
  return $args;
25
  }
26
  }
27
+
lite/includes/libraries/action-scheduler/classes/migration/ActionMigrator.php CHANGED
@@ -79,10 +79,10 @@ class ActionMigrator {
79
 
80
  try {
81
  switch ( $status ) {
82
- case \ActionScheduler_Store::STATUS_FAILED :
83
  $this->destination->mark_failure( $destination_action_id );
84
  break;
85
- case \ActionScheduler_Store::STATUS_CANCELED :
86
  $this->destination->cancel_action( $destination_action_id );
87
  break;
88
  }
79
 
80
  try {
81
  switch ( $status ) {
82
+ case \ActionScheduler_Store::STATUS_FAILED:
83
  $this->destination->mark_failure( $destination_action_id );
84
  break;
85
+ case \ActionScheduler_Store::STATUS_CANCELED:
86
  $this->destination->cancel_action( $destination_action_id );
87
  break;
88
  }
lite/includes/libraries/action-scheduler/classes/migration/ActionScheduler_DBStoreMigrator.php CHANGED
@@ -17,13 +17,13 @@ class ActionScheduler_DBStoreMigrator extends ActionScheduler_DBStore {
17
  * that when first saving the action.
18
  *
19
  * @param ActionScheduler_Action $action
20
- * @param \DateTime $scheduled_date Optional date of the first instance to store.
21
- * @param \DateTime $last_attempt_date Optional date the action was last attempted.
22
  *
23
  * @return string The action ID
24
  * @throws \RuntimeException When the action is not saved.
25
  */
26
- public function save_action( ActionScheduler_Action $action, \DateTime $scheduled_date = null, \DateTime $last_attempt_date = null ){
27
  try {
28
  /** @var \wpdb $wpdb */
29
  global $wpdb;
@@ -31,10 +31,10 @@ class ActionScheduler_DBStoreMigrator extends ActionScheduler_DBStore {
31
  $action_id = parent::save_action( $action, $scheduled_date );
32
 
33
  if ( null !== $last_attempt_date ) {
34
- $data = [
35
  'last_attempt_gmt' => $this->get_scheduled_date_string( $action, $last_attempt_date ),
36
  'last_attempt_local' => $this->get_scheduled_date_string_local( $action, $last_attempt_date ),
37
- ];
38
 
39
  $wpdb->update( $wpdb->actionscheduler_actions, $data, array( 'action_id' => $action_id ), array( '%s', '%s' ), array( '%d' ) );
40
  }
17
  * that when first saving the action.
18
  *
19
  * @param ActionScheduler_Action $action
20
+ * @param \DateTime $scheduled_date Optional date of the first instance to store.
21
+ * @param \DateTime $last_attempt_date Optional date the action was last attempted.
22
  *
23
  * @return string The action ID
24
  * @throws \RuntimeException When the action is not saved.
25
  */
26
+ public function save_action( ActionScheduler_Action $action, \DateTime $scheduled_date = null, \DateTime $last_attempt_date = null ) {
27
  try {
28
  /** @var \wpdb $wpdb */
29
  global $wpdb;
31
  $action_id = parent::save_action( $action, $scheduled_date );
32
 
33
  if ( null !== $last_attempt_date ) {
34
+ $data = array(
35
  'last_attempt_gmt' => $this->get_scheduled_date_string( $action, $last_attempt_date ),
36
  'last_attempt_local' => $this->get_scheduled_date_string_local( $action, $last_attempt_date ),
37
+ );
38
 
39
  $wpdb->update( $wpdb->actionscheduler_actions, $data, array( 'action_id' => $action_id ), array( '%s', '%s' ), array( '%d' ) );
40
  }
lite/includes/libraries/action-scheduler/classes/migration/BatchFetcher.php CHANGED
@@ -3,7 +3,6 @@
3
 
4
  namespace Action_Scheduler\Migration;
5
 
6
-
7
  use ActionScheduler_Store as Store;
8
 
9
  /**
@@ -43,7 +42,7 @@ class BatchFetcher {
43
  }
44
  }
45
 
46
- return [];
47
  }
48
 
49
  /**
@@ -55,32 +54,38 @@ class BatchFetcher {
55
  */
56
  private function get_query_strategies( $count ) {
57
  $now = as_get_datetime_object();
58
- $args = [
59
  'date' => $now,
60
  'per_page' => $count,
61
  'offset' => 0,
62
  'orderby' => 'date',
63
  'order' => 'ASC',
64
- ];
65
 
66
- $priorities = [
67
  Store::STATUS_PENDING,
68
  Store::STATUS_FAILED,
69
  Store::STATUS_CANCELED,
70
  Store::STATUS_COMPLETE,
71
  Store::STATUS_RUNNING,
72
  '', // any other unanticipated status
73
- ];
74
 
75
  foreach ( $priorities as $status ) {
76
- yield wp_parse_args( [
77
- 'status' => $status,
78
- 'date_compare' => '<=',
79
- ], $args );
80
- yield wp_parse_args( [
81
- 'status' => $status,
82
- 'date_compare' => '>=',
83
- ], $args );
 
 
 
 
 
 
84
  }
85
  }
86
- }
3
 
4
  namespace Action_Scheduler\Migration;
5
 
 
6
  use ActionScheduler_Store as Store;
7
 
8
  /**
42
  }
43
  }
44
 
45
+ return array();
46
  }
47
 
48
  /**
54
  */
55
  private function get_query_strategies( $count ) {
56
  $now = as_get_datetime_object();
57
+ $args = array(
58
  'date' => $now,
59
  'per_page' => $count,
60
  'offset' => 0,
61
  'orderby' => 'date',
62
  'order' => 'ASC',
63
+ );
64
 
65
+ $priorities = array(
66
  Store::STATUS_PENDING,
67
  Store::STATUS_FAILED,
68
  Store::STATUS_CANCELED,
69
  Store::STATUS_COMPLETE,
70
  Store::STATUS_RUNNING,
71
  '', // any other unanticipated status
72
+ );
73
 
74
  foreach ( $priorities as $status ) {
75
+ yield wp_parse_args(
76
+ array(
77
+ 'status' => $status,
78
+ 'date_compare' => '<=',
79
+ ),
80
+ $args
81
+ );
82
+ yield wp_parse_args(
83
+ array(
84
+ 'status' => $status,
85
+ 'date_compare' => '>=',
86
+ ),
87
+ $args
88
+ );
89
  }
90
  }
91
+ }
lite/includes/libraries/action-scheduler/classes/migration/DryRun_LogMigrator.php CHANGED
@@ -20,4 +20,4 @@ class DryRun_LogMigrator extends LogMigrator {
20
  public function migrate( $source_action_id, $destination_action_id ) {
21
  // no-op
22
  }
23
- }
20
  public function migrate( $source_action_id, $destination_action_id ) {
21
  // no-op
22
  }
23
+ }
lite/includes/libraries/action-scheduler/classes/migration/Runner.php CHANGED
@@ -70,7 +70,7 @@ class Runner {
70
  * @return int Size of batch processed.
71
  */
72
  public function run( $batch_size = 10 ) {
73
- $batch = $this->batch_fetcher->fetch( $batch_size );
74
  $batch_size = count( $batch );
75
 
76
  if ( ! $batch_size ) {
@@ -102,14 +102,17 @@ class Runner {
102
  foreach ( $action_ids as $source_action_id ) {
103
  $destination_action_id = $this->action_migrator->migrate( $source_action_id );
104
  if ( $destination_action_id ) {
105
- $this->destination_logger->log( $destination_action_id, sprintf(
106
- /* translators: 1: source action ID 2: source store class 3: destination action ID 4: destination store class */
107
- __( 'Migrated action with ID %1$d in %2$s to ID %3$d in %4$s', 'action-scheduler' ),
108
- $source_action_id,
109
- get_class( $this->source_store ),
110
  $destination_action_id,
111
- get_class( $this->destination_store )
112
- ) );
 
 
 
 
 
 
 
113
  }
114
 
115
  if ( $this->progress_bar ) {
70
  * @return int Size of batch processed.
71
  */
72
  public function run( $batch_size = 10 ) {
73
+ $batch = $this->batch_fetcher->fetch( $batch_size );
74
  $batch_size = count( $batch );
75
 
76
  if ( ! $batch_size ) {
102
  foreach ( $action_ids as $source_action_id ) {
103
  $destination_action_id = $this->action_migrator->migrate( $source_action_id );
104
  if ( $destination_action_id ) {
105
+ $this->destination_logger->log(
 
 
 
 
106
  $destination_action_id,
107
+ sprintf(
108
+ /* translators: 1: source action ID 2: source store class 3: destination action ID 4: destination store class */
109
+ __( 'Migrated action with ID %1$d in %2$s to ID %3$d in %4$s', 'action-scheduler' ),
110
+ $source_action_id,
111
+ get_class( $this->source_store ),
112
+ $destination_action_id,
113
+ get_class( $this->destination_store )
114
+ )
115
+ );
116
  }
117
 
118
  if ( $this->progress_bar ) {
lite/includes/libraries/action-scheduler/classes/migration/Scheduler.php CHANGED
@@ -14,10 +14,10 @@ namespace Action_Scheduler\Migration;
14
  */
15
  class Scheduler {
16
  /** Migration action hook. */
17
- const HOOK = 'action_scheduler/migration_hook';
18
 
19
  /** Migration action group. */
20
- const GROUP = 'action-scheduler-migration';
21
 
22
  /**
23
  * Set up the callback for the scheduled job.
14
  */
15
  class Scheduler {
16
  /** Migration action hook. */
17
+ const HOOK = 'action_scheduler/migration_hook';
18
 
19
  /** Migration action group. */
20
+ const GROUP = 'action-scheduler-migration';
21
 
22
  /**
23
  * Set up the callback for the scheduled job.
lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_CanceledSchedule.php CHANGED
@@ -8,7 +8,7 @@ class ActionScheduler_CanceledSchedule extends ActionScheduler_SimpleSchedule {
8
  /**
9
  * Deprecated property @see $this->__wakeup() for details.
10
  **/
11
- private $timestamp = NULL;
12
 
13
  /**
14
  * @param DateTime $after
8
  /**
9
  * Deprecated property @see $this->__wakeup() for details.
10
  **/
11
+ private $timestamp = null;
12
 
13
  /**
14
  * @param DateTime $after
lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_CronSchedule.php CHANGED
@@ -8,20 +8,20 @@ class ActionScheduler_CronSchedule extends ActionScheduler_Abstract_RecurringSch
8
  /**
9
  * Deprecated property @see $this->__wakeup() for details.
10
  **/
11
- private $start_timestamp = NULL;
12
 
13
  /**
14
  * Deprecated property @see $this->__wakeup() for details.
15
  **/
16
- private $cron = NULL;
17
 
18
  /**
19
  * Wrapper for parent constructor to accept a cron expression string and map it to a CronExpression for this
20
  * objects $recurrence property.
21
  *
22
- * @param DateTime $start The date & time to run the action at or after. If $start aligns with the CronSchedule passed via $recurrence, it will be used. If it does not align, the first matching date after it will be used.
23
  * @param CronExpression|string $recurrence The CronExpression used to calculate the schedule's next instance.
24
- * @param DateTime|null $first (Optional) The date & time the first instance of this interval schedule ran. Default null, meaning this is the first instance.
25
  */
26
  public function __construct( DateTime $start, $recurrence, DateTime $first = null ) {
27
  if ( ! is_a( $recurrence, 'CronExpression' ) ) {
@@ -75,10 +75,13 @@ class ActionScheduler_CronSchedule extends ActionScheduler_Abstract_RecurringSch
75
  $this->start_timestamp = $this->scheduled_timestamp;
76
  $this->cron = $this->recurrence;
77
 
78
- return array_merge( $sleep_params, array(
79
- 'start_timestamp',
80
- 'cron'
81
- ) );
 
 
 
82
  }
83
 
84
  /**
8
  /**
9
  * Deprecated property @see $this->__wakeup() for details.
10
  **/
11
+ private $start_timestamp = null;
12
 
13
  /**
14
  * Deprecated property @see $this->__wakeup() for details.
15
  **/
16
+ private $cron = null;
17
 
18
  /**
19
  * Wrapper for parent constructor to accept a cron expression string and map it to a CronExpression for this
20
  * objects $recurrence property.
21
  *
22
+ * @param DateTime $start The date & time to run the action at or after. If $start aligns with the CronSchedule passed via $recurrence, it will be used. If it does not align, the first matching date after it will be used.
23
  * @param CronExpression|string $recurrence The CronExpression used to calculate the schedule's next instance.
24
+ * @param DateTime|null $first (Optional) The date & time the first instance of this interval schedule ran. Default null, meaning this is the first instance.
25
  */
26
  public function __construct( DateTime $start, $recurrence, DateTime $first = null ) {
27
  if ( ! is_a( $recurrence, 'CronExpression' ) ) {
75
  $this->start_timestamp = $this->scheduled_timestamp;
76
  $this->cron = $this->recurrence;
77
 
78
+ return array_merge(
79
+ $sleep_params,
80
+ array(
81
+ 'start_timestamp',
82
+ 'cron',
83
+ )
84
+ );
85
  }
86
 
87
  /**
lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_IntervalSchedule.php CHANGED
@@ -8,12 +8,12 @@ class ActionScheduler_IntervalSchedule extends ActionScheduler_Abstract_Recurrin
8
  /**
9
  * Deprecated property @see $this->__wakeup() for details.
10
  **/
11
- private $start_timestamp = NULL;
12
 
13
  /**
14
  * Deprecated property @see $this->__wakeup() for details.
15
  **/
16
- private $interval_in_seconds = NULL;
17
 
18
  /**
19
  * Calculate when this schedule should start after a given date & time using
@@ -55,10 +55,13 @@ class ActionScheduler_IntervalSchedule extends ActionScheduler_Abstract_Recurrin
55
  $this->start_timestamp = $this->scheduled_timestamp;
56
  $this->interval_in_seconds = $this->recurrence;
57
 
58
- return array_merge( $sleep_params, array(
59
- 'start_timestamp',
60
- 'interval_in_seconds'
61
- ) );
 
 
 
62
  }
63
 
64
  /**
8
  /**
9
  * Deprecated property @see $this->__wakeup() for details.
10
  **/
11
+ private $start_timestamp = null;
12
 
13
  /**
14
  * Deprecated property @see $this->__wakeup() for details.
15
  **/
16
+ private $interval_in_seconds = null;
17
 
18
  /**
19
  * Calculate when this schedule should start after a given date & time using
55
  $this->start_timestamp = $this->scheduled_timestamp;
56
  $this->interval_in_seconds = $this->recurrence;
57
 
58
+ return array_merge(
59
+ $sleep_params,
60
+ array(
61
+ 'start_timestamp',
62
+ 'interval_in_seconds',
63
+ )
64
+ );
65
  }
66
 
67
  /**
lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_NullSchedule.php CHANGED
@@ -16,6 +16,7 @@ class ActionScheduler_NullSchedule extends ActionScheduler_SimpleSchedule {
16
 
17
  /**
18
  * This schedule has no scheduled DateTime, so we need to override the parent __sleep()
 
19
  * @return array
20
  */
21
  public function __sleep() {
16
 
17
  /**
18
  * This schedule has no scheduled DateTime, so we need to override the parent __sleep()
19
+ *
20
  * @return array
21
  */
22
  public function __sleep() {
lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_Schedule.php CHANGED
@@ -8,11 +8,11 @@ interface ActionScheduler_Schedule {
8
  * @param DateTime $after
9
  * @return DateTime|null
10
  */
11
- public function next( DateTime $after = NULL );
12
 
13
  /**
14
  * @return bool
15
  */
16
  public function is_recurring();
17
  }
18
-
8
  * @param DateTime $after
9
  * @return DateTime|null
10
  */
11
+ public function next( DateTime $after = null );
12
 
13
  /**
14
  * @return bool
15
  */
16
  public function is_recurring();
17
  }
18
+
lite/includes/libraries/action-scheduler/classes/schedules/ActionScheduler_SimpleSchedule.php CHANGED
@@ -8,7 +8,7 @@ class ActionScheduler_SimpleSchedule extends ActionScheduler_Abstract_Schedule {
8
  /**
9
  * Deprecated property @see $this->__wakeup() for details.
10
  **/
11
- private $timestamp = NULL;
12
 
13
  /**
14
  * @param DateTime $after
@@ -45,9 +45,12 @@ class ActionScheduler_SimpleSchedule extends ActionScheduler_Abstract_Schedule {
45
 
46
  $this->timestamp = $this->scheduled_timestamp;
47
 
48
- return array_merge( $sleep_params, array(
49
- 'timestamp',
50
- ) );
 
 
 
51
  }
52
 
53
  /**
8
  /**
9
  * Deprecated property @see $this->__wakeup() for details.
10
  **/
11
+ private $timestamp = null;
12
 
13
  /**
14
  * @param DateTime $after
45
 
46
  $this->timestamp = $this->scheduled_timestamp;
47
 
48
+ return array_merge(
49
+ $sleep_params,
50
+ array(
51
+ 'timestamp',
52
+ )
53
+ );
54
  }
55
 
56
  /**
lite/includes/libraries/action-scheduler/classes/schema/ActionScheduler_LoggerSchema.php CHANGED
@@ -16,19 +16,18 @@ class ActionScheduler_LoggerSchema extends ActionScheduler_Abstract_Schema {
16
  protected $schema_version = 2;
17
 
18
  public function __construct() {
19
- $this->tables = [
20
  self::LOG_TABLE,
21
- ];
22
  }
23
 
24
  protected function get_table_definition( $table ) {
25
  global $wpdb;
26
- $table_name = $wpdb->$table;
27
- $charset_collate = $wpdb->get_charset_collate();
28
  switch ( $table ) {
29
 
30
  case self::LOG_TABLE:
31
-
32
  return "CREATE TABLE {$table_name} (
33
  log_id bigint(20) unsigned NOT NULL auto_increment,
34
  action_id bigint(20) unsigned NOT NULL,
16
  protected $schema_version = 2;
17
 
18
  public function __construct() {
19
+ $this->tables = array(
20
  self::LOG_TABLE,
21
+ );
22
  }
23
 
24
  protected function get_table_definition( $table ) {
25
  global $wpdb;
26
+ $table_name = $wpdb->$table;
27
+ $charset_collate = $wpdb->get_charset_collate();
28
  switch ( $table ) {
29
 
30
  case self::LOG_TABLE:
 
31
  return "CREATE TABLE {$table_name} (
32
  log_id bigint(20) unsigned NOT NULL auto_increment,
33
  action_id bigint(20) unsigned NOT NULL,
lite/includes/libraries/action-scheduler/classes/schema/ActionScheduler_StoreSchema.php CHANGED
@@ -18,11 +18,11 @@ class ActionScheduler_StoreSchema extends ActionScheduler_Abstract_Schema {
18
  protected $schema_version = 3;
19
 
20
  public function __construct() {
21
- $this->tables = [
22
  self::ACTIONS_TABLE,
23
  self::CLAIMS_TABLE,
24
  self::GROUPS_TABLE,
25
- ];
26
  }
27
 
28
  protected function get_table_definition( $table ) {
@@ -33,7 +33,6 @@ class ActionScheduler_StoreSchema extends ActionScheduler_Abstract_Schema {
33
  switch ( $table ) {
34
 
35
  case self::ACTIONS_TABLE:
36
-
37
  return "CREATE TABLE {$table_name} (
38
  action_id bigint(20) unsigned NOT NULL auto_increment,
39
  hook varchar(191) NOT NULL,
@@ -59,7 +58,6 @@ class ActionScheduler_StoreSchema extends ActionScheduler_Abstract_Schema {
59
  ) $charset_collate";
60
 
61
  case self::CLAIMS_TABLE:
62
-
63
  return "CREATE TABLE {$table_name} (
64
  claim_id bigint(20) unsigned NOT NULL auto_increment,
65
  date_created_gmt datetime NOT NULL default '0000-00-00 00:00:00',
@@ -68,7 +66,6 @@ class ActionScheduler_StoreSchema extends ActionScheduler_Abstract_Schema {
68
  ) $charset_collate";
69
 
70
  case self::GROUPS_TABLE:
71
-
72
  return "CREATE TABLE {$table_name} (
73
  group_id bigint(20) unsigned NOT NULL auto_increment,
74
  slug varchar(255) NOT NULL,
18
  protected $schema_version = 3;
19
 
20
  public function __construct() {
21
+ $this->tables = array(
22
  self::ACTIONS_TABLE,
23
  self::CLAIMS_TABLE,
24
  self::GROUPS_TABLE,
25
+ );
26
  }
27
 
28
  protected function get_table_definition( $table ) {
33
  switch ( $table ) {
34
 
35
  case self::ACTIONS_TABLE:
 
36
  return "CREATE TABLE {$table_name} (
37
  action_id bigint(20) unsigned NOT NULL auto_increment,
38
  hook varchar(191) NOT NULL,
58
  ) $charset_collate";
59
 
60
  case self::CLAIMS_TABLE:
 
61
  return "CREATE TABLE {$table_name} (
62
  claim_id bigint(20) unsigned NOT NULL auto_increment,
63
  date_created_gmt datetime NOT NULL default '0000-00-00 00:00:00',
66
  ) $charset_collate";
67
 
68
  case self::GROUPS_TABLE:
 
69
  return "CREATE TABLE {$table_name} (
70
  group_id bigint(20) unsigned NOT NULL auto_increment,
71
  slug varchar(255) NOT NULL,
lite/includes/libraries/action-scheduler/deprecated/ActionScheduler_AdminView_Deprecated.php CHANGED
@@ -68,7 +68,7 @@ class ActionScheduler_AdminView_Deprecated {
68
  * Print the content for our custom columns.
69
  *
70
  * @param string $column_name The key for the column for which we should output our content.
71
- * @param int $post_id The ID of the 'scheduled-action' post for which this row relates.
72
  */
73
  public static function list_table_column_content( $column_name, $post_id ) {
74
  _deprecated_function( __METHOD__, '2.0.0' );
@@ -115,18 +115,18 @@ class ActionScheduler_AdminView_Deprecated {
115
  /**
116
  * Filter search queries to allow searching by Claim ID (i.e. post_password).
117
  *
118
- * @param string $orderby MySQL orderby string.
119
  * @param WP_Query $query Instance of a WP_Query object
120
  * @return string MySQL orderby string.
121
  */
122
- public function custom_orderby( $orderby, $query ){
123
  _deprecated_function( __METHOD__, '2.0.0' );
124
  }
125
 
126
  /**
127
  * Filter search queries to allow searching by Claim ID (i.e. post_password).
128
  *
129
- * @param string $search MySQL search string.
130
  * @param WP_Query $query Instance of a WP_Query object
131
  * @return string MySQL search string.
132
  */
@@ -144,4 +144,4 @@ class ActionScheduler_AdminView_Deprecated {
144
  _deprecated_function( __METHOD__, '2.0.0' );
145
  return $messages;
146
  }
147
- }
68
  * Print the content for our custom columns.
69
  *
70
  * @param string $column_name The key for the column for which we should output our content.
71
+ * @param int $post_id The ID of the 'scheduled-action' post for which this row relates.
72
  */
73
  public static function list_table_column_content( $column_name, $post_id ) {
74
  _deprecated_function( __METHOD__, '2.0.0' );
115
  /**
116
  * Filter search queries to allow searching by Claim ID (i.e. post_password).
117
  *
118
+ * @param string $orderby MySQL orderby string.
119
  * @param WP_Query $query Instance of a WP_Query object
120
  * @return string MySQL orderby string.
121
  */
122
+ public function custom_orderby( $orderby, $query ) {
123
  _deprecated_function( __METHOD__, '2.0.0' );
124
  }
125
 
126
  /**
127
  * Filter search queries to allow searching by Claim ID (i.e. post_password).
128
  *
129
+ * @param string $search MySQL search string.
130
  * @param WP_Query $query Instance of a WP_Query object
131
  * @return string MySQL search string.
132
  */
144
  _deprecated_function( __METHOD__, '2.0.0' );
145
  return $messages;
146
  }
147
+ }
lite/includes/libraries/action-scheduler/deprecated/ActionScheduler_Schedule_Deprecated.php CHANGED
@@ -13,7 +13,7 @@ abstract class ActionScheduler_Schedule_Deprecated implements ActionScheduler_Sc
13
  *
14
  * @return DateTime|null
15
  */
16
- public function next( DateTime $after = NULL ) {
17
  if ( empty( $after ) ) {
18
  $return_value = $this->get_date();
19
  $replacement_method = 'get_date()';
13
  *
14
  * @return DateTime|null
15
  */
16
+ public function next( DateTime $after = null ) {
17
  if ( empty( $after ) ) {
18
  $return_value = $this->get_date();
19
  $replacement_method = 'get_date()';
lite/includes/libraries/action-scheduler/deprecated/ActionScheduler_Store_Deprecated.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  /**
4
  * Class ActionScheduler_Store_Deprecated
 
5
  * @codeCoverageIgnore
6
  */
7
  abstract class ActionScheduler_Store_Deprecated {
2
 
3
  /**
4
  * Class ActionScheduler_Store_Deprecated
5
+ *
6
  * @codeCoverageIgnore
7
  */
8
  abstract class ActionScheduler_Store_Deprecated {
lite/includes/libraries/action-scheduler/deprecated/functions.php CHANGED
@@ -11,9 +11,9 @@
11
  /**
12
  * Schedule an action to run one time
13
  *
14
- * @param int $timestamp When the job will run
15
  * @param string $hook The hook to trigger
16
- * @param array $args Arguments to pass when the hook triggers
17
  * @param string $group The group to assign this job to
18
  *
19
  * @return string The job ID
@@ -26,10 +26,10 @@ function wc_schedule_single_action( $timestamp, $hook, $args = array(), $group =
26
  /**
27
  * Schedule a recurring action
28
  *
29
- * @param int $timestamp When the first instance of the job will run
30
- * @param int $interval_in_seconds How long to wait between runs
31
  * @param string $hook The hook to trigger
32
- * @param array $args Arguments to pass when the hook triggers
33
  * @param string $group The group to assign this job to
34
  *
35
  * @deprecated 2.1.0
@@ -44,7 +44,7 @@ function wc_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook,
44
  /**
45
  * Schedule an action that recurs on a cron-like schedule.
46
  *
47
- * @param int $timestamp The schedule will start on or after this time
48
  * @param string $schedule A cron-link schedule string
49
  * @see http://en.wikipedia.org/wiki/Cron
50
  * * * * * * *
@@ -57,7 +57,7 @@ function wc_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook,
57
  * | +-------------------- hour (0 - 23)
58
  * +------------------------- min (0 - 59)
59
  * @param string $hook The hook to trigger
60
- * @param array $args Arguments to pass when the hook triggers
61
  * @param string $group The group to assign this job to
62
  *
63
  * @deprecated 2.1.0
@@ -73,7 +73,7 @@ function wc_schedule_cron_action( $timestamp, $schedule, $hook, $args = array(),
73
  * Cancel the next occurrence of a job.
74
  *
75
  * @param string $hook The hook that the job will trigger
76
- * @param array $args Args that would have been passed to the job
77
  * @param string $group
78
  *
79
  * @deprecated 2.1.0
@@ -85,14 +85,14 @@ function wc_unschedule_action( $hook, $args = array(), $group = '' ) {
85
 
86
  /**
87
  * @param string $hook
88
- * @param array $args
89
  * @param string $group
90
  *
91
  * @deprecated 2.1.0
92
  *
93
  * @return int|bool The timestamp for the next occurrence, or false if nothing was found
94
  */
95
- function wc_next_scheduled_action( $hook, $args = NULL, $group = '' ) {
96
  _deprecated_function( __FUNCTION__, '2.1.0', 'as_next_scheduled_action()' );
97
  return as_next_scheduled_action( $hook, $args, $group );
98
  }
@@ -100,20 +100,20 @@ function wc_next_scheduled_action( $hook, $args = NULL, $group = '' ) {
100
  /**
101
  * Find scheduled actions
102
  *
103
- * @param array $args Possible arguments, with their default values:
104
- * 'hook' => '' - the name of the action that will be triggered
105
- * 'args' => NULL - the args array that will be passed with the action
106
- * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
107
- * 'date_compare' => '<=' - operator for testing "date". accepted values are '!=', '>', '>=', '<', '<=', '='
108
- * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
109
- * 'modified_compare' => '<=' - operator for testing "modified". accepted values are '!=', '>', '>=', '<', '<=', '='
110
- * 'group' => '' - the group the action belongs to
111
- * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING
112
- * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID
113
- * 'per_page' => 5 - Number of results to return
114
- * 'offset' => 0
115
- * 'orderby' => 'date' - accepted values are 'hook', 'group', 'modified', or 'date'
116
- * 'order' => 'ASC'
117
  * @param string $return_format OBJECT, ARRAY_A, or ids
118
  *
119
  * @deprecated 2.1.0
11
  /**
12
  * Schedule an action to run one time
13
  *
14
+ * @param int $timestamp When the job will run
15
  * @param string $hook The hook to trigger
16
+ * @param array $args Arguments to pass when the hook triggers
17
  * @param string $group The group to assign this job to
18
  *
19
  * @return string The job ID
26
  /**
27
  * Schedule a recurring action
28
  *
29
+ * @param int $timestamp When the first instance of the job will run
30
+ * @param int $interval_in_seconds How long to wait between runs
31
  * @param string $hook The hook to trigger
32
+ * @param array $args Arguments to pass when the hook triggers
33
  * @param string $group The group to assign this job to
34
  *
35
  * @deprecated 2.1.0
44
  /**
45
  * Schedule an action that recurs on a cron-like schedule.
46
  *
47
+ * @param int $timestamp The schedule will start on or after this time
48
  * @param string $schedule A cron-link schedule string
49
  * @see http://en.wikipedia.org/wiki/Cron
50
  * * * * * * *
57
  * | +-------------------- hour (0 - 23)
58
  * +------------------------- min (0 - 59)
59
  * @param string $hook The hook to trigger
60
+ * @param array $args Arguments to pass when the hook triggers
61
  * @param string $group The group to assign this job to
62
  *
63
  * @deprecated 2.1.0
73
  * Cancel the next occurrence of a job.
74
  *
75
  * @param string $hook The hook that the job will trigger
76
+ * @param array $args Args that would have been passed to the job
77
  * @param string $group
78
  *
79
  * @deprecated 2.1.0
85
 
86
  /**
87
  * @param string $hook
88
+ * @param array $args
89
  * @param string $group
90
  *
91
  * @deprecated 2.1.0
92
  *
93
  * @return int|bool The timestamp for the next occurrence, or false if nothing was found
94
  */
95
+ function wc_next_scheduled_action( $hook, $args = null, $group = '' ) {
96
  _deprecated_function( __FUNCTION__, '2.1.0', 'as_next_scheduled_action()' );
97
  return as_next_scheduled_action( $hook, $args, $group );
98
  }
100
  /**
101
  * Find scheduled actions
102
  *
103
+ * @param array $args Possible arguments, with their default values:
104
+ * 'hook' => '' - the name of the action that will be triggered
105
+ * 'args' => NULL - the args array that will be passed with the action
106
+ * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
107
+ * 'date_compare' => '<=' - operator for testing "date". accepted values are '!=', '>', '>=', '<', '<=', '='
108
+ * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
109
+ * 'modified_compare' => '<=' - operator for testing "modified". accepted values are '!=', '>', '>=', '<', '<=', '='
110
+ * 'group' => '' - the group the action belongs to
111
+ * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING
112
+ * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID
113
+ * 'per_page' => 5 - Number of results to return
114
+ * 'offset' => 0
115
+ * 'orderby' => 'date' - accepted values are 'hook', 'group', 'modified', or 'date'
116
+ * 'order' => 'ASC'
117
  * @param string $return_format OBJECT, ARRAY_A, or ids
118
  *
119
  * @deprecated 2.1.0
lite/includes/libraries/action-scheduler/functions.php CHANGED
@@ -22,9 +22,9 @@ function as_enqueue_async_action( $hook, $args = array(), $group = '' ) {
22
  /**
23
  * Schedule an action to run one time
24
  *
25
- * @param int $timestamp When the job will run.
26
  * @param string $hook The hook to trigger.
27
- * @param array $args Arguments to pass when the hook triggers.
28
  * @param string $group The group to assign this job to.
29
  *
30
  * @return int The action ID.
@@ -39,10 +39,10 @@ function as_schedule_single_action( $timestamp, $hook, $args = array(), $group =
39
  /**
40
  * Schedule a recurring action
41
  *
42
- * @param int $timestamp When the first instance of the job will run.
43
- * @param int $interval_in_seconds How long to wait between runs.
44
  * @param string $hook The hook to trigger.
45
- * @param array $args Arguments to pass when the hook triggers.
46
  * @param string $group The group to assign this job to.
47
  *
48
  * @return int The action ID.
@@ -57,9 +57,9 @@ function as_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook,
57
  /**
58
  * Schedule an action that recurs on a cron-like schedule.
59
  *
60
- * @param int $base_timestamp The first instance of the action will be scheduled
61
- * to run at a time calculated after this timestamp matching the cron
62
- * expression. This can be used to delay the first instance of the action.
63
  * @param string $schedule A cron-link schedule string
64
  * @see http://en.wikipedia.org/wiki/Cron
65
  * * * * * * *
@@ -72,7 +72,7 @@ function as_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook,
72
  * | +-------------------- hour (0 - 23)
73
  * +------------------------- min (0 - 59)
74
  * @param string $hook The hook to trigger.
75
- * @param array $args Arguments to pass when the hook triggers.
76
  * @param string $group The group to assign this job to.
77
  *
78
  * @return int The action ID.
@@ -95,7 +95,7 @@ function as_schedule_cron_action( $timestamp, $schedule, $hook, $args = array(),
95
  * by this method also.
96
  *
97
  * @param string $hook The hook that the job will trigger.
98
- * @param array $args Args that would have been passed to the job.
99
  * @param string $group The group the job is assigned to.
100
  *
101
  * @return string|null The scheduled action ID if a scheduled action was found, or null if no matching action found.
@@ -105,10 +105,10 @@ function as_unschedule_action( $hook, $args = array(), $group = '' ) {
105
  return 0;
106
  }
107
  $params = array();
108
- if ( is_array($args) ) {
109
  $params['args'] = $args;
110
  }
111
- if ( !empty($group) ) {
112
  $params['group'] = $group;
113
  }
114
  $job_id = ActionScheduler::store()->find_action( $hook, $params );
@@ -124,7 +124,7 @@ function as_unschedule_action( $hook, $args = array(), $group = '' ) {
124
  * Cancel all occurrences of a scheduled action.
125
  *
126
  * @param string $hook The hook that the job will trigger.
127
- * @param array $args Args that would have been passed to the job.
128
  * @param string $group The group the job is assigned to.
129
  */
130
  function as_unschedule_all_actions( $hook, $args = array(), $group = '' ) {
@@ -156,39 +156,39 @@ function as_unschedule_all_actions( $hook, $args = array(), $group = '' ) {
156
  * boolean false will be the return value.
157
  *
158
  * @param string $hook
159
- * @param array $args
160
  * @param string $group
161
  *
162
  * @return int|bool The timestamp for the next occurrence of a pending scheduled action, true for an async or in-progress action or false if there is no matching action.
163
  */
164
- function as_next_scheduled_action( $hook, $args = NULL, $group = '' ) {
165
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
166
  return false;
167
  }
168
  $params = array();
169
- if ( is_array($args) ) {
170
  $params['args'] = $args;
171
  }
172
- if ( !empty($group) ) {
173
  $params['group'] = $group;
174
  }
175
 
176
  $params['status'] = ActionScheduler_Store::STATUS_RUNNING;
177
- $job_id = ActionScheduler::store()->find_action( $hook, $params );
178
  if ( ! empty( $job_id ) ) {
179
  return true;
180
  }
181
 
182
  $params['status'] = ActionScheduler_Store::STATUS_PENDING;
183
- $job_id = ActionScheduler::store()->find_action( $hook, $params );
184
- if ( empty($job_id) ) {
185
  return false;
186
  }
187
- $job = ActionScheduler::store()->fetch_action( $job_id );
188
  $scheduled_date = $job->get_schedule()->get_date();
189
  if ( $scheduled_date ) {
190
  return (int) $scheduled_date->format( 'U' );
191
- } elseif ( NULL === $scheduled_date ) { // pending async action with NullSchedule
192
  return true;
193
  }
194
  return false;
@@ -197,20 +197,20 @@ function as_next_scheduled_action( $hook, $args = NULL, $group = '' ) {
197
  /**
198
  * Find scheduled actions
199
  *
200
- * @param array $args Possible arguments, with their default values:
201
- * 'hook' => '' - the name of the action that will be triggered
202
- * 'args' => NULL - the args array that will be passed with the action
203
- * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
204
- * 'date_compare' => '<=' - operator for testing "date". accepted values are '!=', '>', '>=', '<', '<=', '='
205
- * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
206
- * 'modified_compare' => '<=' - operator for testing "modified". accepted values are '!=', '>', '>=', '<', '<=', '='
207
- * 'group' => '' - the group the action belongs to
208
- * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING
209
- * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID
210
- * 'per_page' => 5 - Number of results to return
211
- * 'offset' => 0
212
- * 'orderby' => 'date' - accepted values are 'hook', 'group', 'modified', or 'date'
213
- * 'order' => 'ASC'
214
  *
215
  * @param string $return_format OBJECT, ARRAY_A, or ids.
216
  *
@@ -221,9 +221,9 @@ function as_get_scheduled_actions( $args = array(), $return_format = OBJECT ) {
221
  return array();
222
  }
223
  $store = ActionScheduler::store();
224
- foreach ( array('date', 'modified') as $key ) {
225
- if ( isset($args[$key]) ) {
226
- $args[$key] = as_get_datetime_object($args[$key]);
227
  }
228
  }
229
  $ids = $store->query_actions( $args );
@@ -234,12 +234,12 @@ function as_get_scheduled_actions( $args = array(), $return_format = OBJECT ) {
234
 
235
  $actions = array();
236
  foreach ( $ids as $action_id ) {
237
- $actions[$action_id] = $store->fetch_action( $action_id );
238
  }
239
 
240
  if ( $return_format == ARRAY_A ) {
241
  foreach ( $actions as $action_id => $action_object ) {
242
- $actions[$action_id] = get_object_vars($action_object);
243
  }
244
  }
245
 
@@ -258,7 +258,7 @@ function as_get_scheduled_actions( $args = array(), $return_format = OBJECT ) {
258
  * timezone when instantiating datetimes rather than leaving it up to
259
  * the PHP default.
260
  *
261
- * @param mixed $date_string A date/time string. Valid formats are explained in http://php.net/manual/en/datetime.formats.php.
262
  * @param string $timezone A timezone identifier, like UTC or Europe/Lisbon. The list of valid identifiers is available http://php.net/manual/en/timezones.php.
263
  *
264
  * @return ActionScheduler_DateTime
22
  /**
23
  * Schedule an action to run one time
24
  *
25
+ * @param int $timestamp When the job will run.
26
  * @param string $hook The hook to trigger.
27
+ * @param array $args Arguments to pass when the hook triggers.
28
  * @param string $group The group to assign this job to.
29
  *
30
  * @return int The action ID.
39
  /**
40
  * Schedule a recurring action
41
  *
42
+ * @param int $timestamp When the first instance of the job will run.
43
+ * @param int $interval_in_seconds How long to wait between runs.
44
  * @param string $hook The hook to trigger.
45
+ * @param array $args Arguments to pass when the hook triggers.
46
  * @param string $group The group to assign this job to.
47
  *
48
  * @return int The action ID.
57
  /**
58
  * Schedule an action that recurs on a cron-like schedule.
59
  *
60
+ * @param int $base_timestamp The first instance of the action will be scheduled
61
+ * to run at a time calculated after this timestamp matching the cron
62
+ * expression. This can be used to delay the first instance of the action.
63
  * @param string $schedule A cron-link schedule string
64
  * @see http://en.wikipedia.org/wiki/Cron
65
  * * * * * * *
72
  * | +-------------------- hour (0 - 23)
73
  * +------------------------- min (0 - 59)
74
  * @param string $hook The hook to trigger.
75
+ * @param array $args Arguments to pass when the hook triggers.
76
  * @param string $group The group to assign this job to.
77
  *
78
  * @return int The action ID.
95
  * by this method also.
96
  *
97
  * @param string $hook The hook that the job will trigger.
98
+ * @param array $args Args that would have been passed to the job.
99
  * @param string $group The group the job is assigned to.
100
  *
101
  * @return string|null The scheduled action ID if a scheduled action was found, or null if no matching action found.
105
  return 0;
106
  }
107
  $params = array();
108
+ if ( is_array( $args ) ) {
109
  $params['args'] = $args;
110
  }
111
+ if ( ! empty( $group ) ) {
112
  $params['group'] = $group;
113
  }
114
  $job_id = ActionScheduler::store()->find_action( $hook, $params );
124
  * Cancel all occurrences of a scheduled action.
125
  *
126
  * @param string $hook The hook that the job will trigger.
127
+ * @param array $args Args that would have been passed to the job.
128
  * @param string $group The group the job is assigned to.
129
  */
130
  function as_unschedule_all_actions( $hook, $args = array(), $group = '' ) {
156
  * boolean false will be the return value.
157
  *
158
  * @param string $hook
159
+ * @param array $args
160
  * @param string $group
161
  *
162
  * @return int|bool The timestamp for the next occurrence of a pending scheduled action, true for an async or in-progress action or false if there is no matching action.
163
  */
164
+ function as_next_scheduled_action( $hook, $args = null, $group = '' ) {
165
  if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) {
166
  return false;
167
  }
168
  $params = array();
169
+ if ( is_array( $args ) ) {
170
  $params['args'] = $args;
171
  }
172
+ if ( ! empty( $group ) ) {
173
  $params['group'] = $group;
174
  }
175
 
176
  $params['status'] = ActionScheduler_Store::STATUS_RUNNING;
177
+ $job_id = ActionScheduler::store()->find_action( $hook, $params );
178
  if ( ! empty( $job_id ) ) {
179
  return true;
180
  }
181
 
182
  $params['status'] = ActionScheduler_Store::STATUS_PENDING;
183
+ $job_id = ActionScheduler::store()->find_action( $hook, $params );
184
+ if ( empty( $job_id ) ) {
185
  return false;
186
  }
187
+ $job = ActionScheduler::store()->fetch_action( $job_id );
188
  $scheduled_date = $job->get_schedule()->get_date();
189
  if ( $scheduled_date ) {
190
  return (int) $scheduled_date->format( 'U' );
191
+ } elseif ( null === $scheduled_date ) { // pending async action with NullSchedule
192
  return true;
193
  }
194
  return false;
197
  /**
198
  * Find scheduled actions
199
  *
200
+ * @param array $args Possible arguments, with their default values:
201
+ * 'hook' => '' - the name of the action that will be triggered
202
+ * 'args' => NULL - the args array that will be passed with the action
203
+ * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
204
+ * 'date_compare' => '<=' - operator for testing "date". accepted values are '!=', '>', '>=', '<', '<=', '='
205
+ * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone.
206
+ * 'modified_compare' => '<=' - operator for testing "modified". accepted values are '!=', '>', '>=', '<', '<=', '='
207
+ * 'group' => '' - the group the action belongs to
208
+ * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING
209
+ * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID
210
+ * 'per_page' => 5 - Number of results to return
211
+ * 'offset' => 0
212
+ * 'orderby' => 'date' - accepted values are 'hook', 'group', 'modified', or 'date'
213
+ * 'order' => 'ASC'
214
  *
215
  * @param string $return_format OBJECT, ARRAY_A, or ids.
216
  *
221
  return array();
222
  }
223
  $store = ActionScheduler::store();
224
+ foreach ( array( 'date', 'modified' ) as $key ) {
225
+ if ( isset( $args[ $key ] ) ) {
226
+ $args[ $key ] = as_get_datetime_object( $args[ $key ] );
227
  }
228
  }
229
  $ids = $store->query_actions( $args );
234
 
235
  $actions = array();
236
  foreach ( $ids as $action_id ) {
237
+ $actions[ $action_id ] = $store->fetch_action( $action_id );
238
  }
239
 
240
  if ( $return_format == ARRAY_A ) {
241
  foreach ( $actions as $action_id => $action_object ) {
242
+ $actions[ $action_id ] = get_object_vars( $action_object );
243
  }
244
  }
245
 
258
  * timezone when instantiating datetimes rather than leaving it up to
259
  * the PHP default.
260
  *
261
+ * @param mixed $date_string A date/time string. Valid formats are explained in http://php.net/manual/en/datetime.formats.php.
262
  * @param string $timezone A timezone identifier, like UTC or Europe/Lisbon. The list of valid identifiers is available http://php.net/manual/en/timezones.php.
263
  *
264
  * @return ActionScheduler_DateTime
lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression.php CHANGED
@@ -13,306 +13,295 @@
13
  * @author Michael Dowling <mtdowling@gmail.com>
14
  * @link http://en.wikipedia.org/wiki/Cron
15
  */
16
- class CronExpression
17
- {
18
- const MINUTE = 0;
19
- const HOUR = 1;
20
- const DAY = 2;
21
- const MONTH = 3;
22
- const WEEKDAY = 4;
23
- const YEAR = 5;
24
-
25
- /**
26
- * @var array CRON expression parts
27
- */
28
- private $cronParts;
29
-
30
- /**
31
- * @var CronExpression_FieldFactory CRON field factory
32
- */
33
- private $fieldFactory;
34
-
35
- /**
36
- * @var array Order in which to test of cron parts
37
- */
38
- private static $order = array(self::YEAR, self::MONTH, self::DAY, self::WEEKDAY, self::HOUR, self::MINUTE);
39
-
40
- /**
41
- * Factory method to create a new CronExpression.
42
- *
43
- * @param string $expression The CRON expression to create. There are
44
- * several special predefined values which can be used to substitute the
45
- * CRON expression:
46
- *
47
- * @yearly, @annually) - Run once a year, midnight, Jan. 1 - 0 0 1 1 *
48
- * @monthly - Run once a month, midnight, first of month - 0 0 1 * *
49
- * @weekly - Run once a week, midnight on Sun - 0 0 * * 0
50
- * @daily - Run once a day, midnight - 0 0 * * *
51
- * @hourly - Run once an hour, first minute - 0 * * * *
52
- *
53
- *@param CronExpression_FieldFactory $fieldFactory (optional) Field factory to use
54
- *
55
- * @return CronExpression
56
- */
57
- public static function factory($expression, CronExpression_FieldFactory $fieldFactory = null)
58
- {
59
- $mappings = array(
60
- '@yearly' => '0 0 1 1 *',
61
- '@annually' => '0 0 1 1 *',
62
- '@monthly' => '0 0 1 * *',
63
- '@weekly' => '0 0 * * 0',
64
- '@daily' => '0 0 * * *',
65
- '@hourly' => '0 * * * *'
66
- );
67
-
68
- if (isset($mappings[$expression])) {
69
- $expression = $mappings[$expression];
70
- }
71
-
72
- return new self($expression, $fieldFactory ? $fieldFactory : new CronExpression_FieldFactory());
73
- }
74
-
75
- /**
76
- * Parse a CRON expression
77
- *
78
- * @param string $expression CRON expression (e.g. '8 * * * *')
79
- * @param CronExpression_FieldFactory $fieldFactory Factory to create cron fields
80
- */
81
- public function __construct($expression, CronExpression_FieldFactory $fieldFactory)
82
- {
83
- $this->fieldFactory = $fieldFactory;
84
- $this->setExpression($expression);
85
- }
86
-
87
- /**
88
- * Set or change the CRON expression
89
- *
90
- * @param string $value CRON expression (e.g. 8 * * * *)
91
- *
92
- * @return CronExpression
93
- * @throws InvalidArgumentException if not a valid CRON expression
94
- */
95
- public function setExpression($value)
96
- {
97
- $this->cronParts = preg_split('/\s/', $value, -1, PREG_SPLIT_NO_EMPTY);
98
- if (count($this->cronParts) < 5) {
99
- throw new InvalidArgumentException(
100
- $value . ' is not a valid CRON expression'
101
- );
102
- }
103
-
104
- foreach ($this->cronParts as $position => $part) {
105
- $this->setPart($position, $part);
106
- }
107
-
108
- return $this;
109
- }
110
-
111
- /**
112
- * Set part of the CRON expression
113
- *
114
- * @param int $position The position of the CRON expression to set
115
- * @param string $value The value to set
116
- *
117
- * @return CronExpression
118
- * @throws InvalidArgumentException if the value is not valid for the part
119
- */
120
- public function setPart($position, $value)
121
- {
122
- if (!$this->fieldFactory->getField($position)->validate($value)) {
123
- throw new InvalidArgumentException(
124
- 'Invalid CRON field value ' . $value . ' as position ' . $position
125
- );
126
- }
127
-
128
- $this->cronParts[$position] = $value;
129
-
130
- return $this;
131
- }
132
-
133
- /**
134
- * Get a next run date relative to the current date or a specific date
135
- *
136
- * @param string|DateTime $currentTime (optional) Relative calculation date
137
- * @param int $nth (optional) Number of matches to skip before returning a
138
- * matching next run date. 0, the default, will return the current
139
- * date and time if the next run date falls on the current date and
140
- * time. Setting this value to 1 will skip the first match and go to
141
- * the second match. Setting this value to 2 will skip the first 2
142
- * matches and so on.
143
- * @param bool $allowCurrentDate (optional) Set to TRUE to return the
144
- * current date if it matches the cron expression
145
- *
146
- * @return DateTime
147
- * @throws RuntimeException on too many iterations
148
- */
149
- public function getNextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
150
- {
151
- return $this->getRunDate($currentTime, $nth, false, $allowCurrentDate);
152
- }
153
-
154
- /**
155
- * Get a previous run date relative to the current date or a specific date
156
- *
157
- * @param string|DateTime $currentTime (optional) Relative calculation date
158
- * @param int $nth (optional) Number of matches to skip before returning
159
- * @param bool $allowCurrentDate (optional) Set to TRUE to return the
160
- * current date if it matches the cron expression
161
- *
162
- * @return DateTime
163
- * @throws RuntimeException on too many iterations
164
- * @see CronExpression::getNextRunDate
165
- */
166
- public function getPreviousRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
167
- {
168
- return $this->getRunDate($currentTime, $nth, true, $allowCurrentDate);
169
- }
170
-
171
- /**
172
- * Get multiple run dates starting at the current date or a specific date
173
- *
174
- * @param int $total Set the total number of dates to calculate
175
- * @param string|DateTime $currentTime (optional) Relative calculation date
176
- * @param bool $invert (optional) Set to TRUE to retrieve previous dates
177
- * @param bool $allowCurrentDate (optional) Set to TRUE to return the
178
- * current date if it matches the cron expression
179
- *
180
- * @return array Returns an array of run dates
181
- */
182
- public function getMultipleRunDates($total, $currentTime = 'now', $invert = false, $allowCurrentDate = false)
183
- {
184
- $matches = array();
185
- for ($i = 0; $i < max(0, $total); $i++) {
186
- $matches[] = $this->getRunDate($currentTime, $i, $invert, $allowCurrentDate);
187
- }
188
-
189
- return $matches;
190
- }
191
-
192
- /**
193
- * Get all or part of the CRON expression
194
- *
195
- * @param string $part (optional) Specify the part to retrieve or NULL to
196
- * get the full cron schedule string.
197
- *
198
- * @return string|null Returns the CRON expression, a part of the
199
- * CRON expression, or NULL if the part was specified but not found
200
- */
201
- public function getExpression($part = null)
202
- {
203
- if (null === $part) {
204
- return implode(' ', $this->cronParts);
205
- } elseif (array_key_exists($part, $this->cronParts)) {
206
- return $this->cronParts[$part];
207
- }
208
-
209
- return null;
210
- }
211
-
212
- /**
213
- * Helper method to output the full expression.
214
- *
215
- * @return string Full CRON expression
216
- */
217
- public function __toString()
218
- {
219
- return $this->getExpression();
220
- }
221
-
222
- /**
223
- * Determine if the cron is due to run based on the current date or a
224
- * specific date. This method assumes that the current number of
225
- * seconds are irrelevant, and should be called once per minute.
226
- *
227
- * @param string|DateTime $currentTime (optional) Relative calculation date
228
- *
229
- * @return bool Returns TRUE if the cron is due to run or FALSE if not
230
- */
231
- public function isDue($currentTime = 'now')
232
- {
233
- if ('now' === $currentTime) {
234
- $currentDate = date('Y-m-d H:i');
235
- $currentTime = strtotime($currentDate);
236
- } elseif ($currentTime instanceof DateTime) {
237
- $currentDate = $currentTime->format('Y-m-d H:i');
238
- $currentTime = strtotime($currentDate);
239
- } else {
240
- $currentTime = new DateTime($currentTime);
241
- $currentTime->setTime($currentTime->format('H'), $currentTime->format('i'), 0);
242
- $currentDate = $currentTime->format('Y-m-d H:i');
243
- $currentTime = (int)($currentTime->getTimestamp());
244
- }
245
-
246
- return $this->getNextRunDate($currentDate, 0, true)->getTimestamp() == $currentTime;
247
- }
248
-
249
- /**
250
- * Get the next or previous run date of the expression relative to a date
251
- *
252
- * @param string|DateTime $currentTime (optional) Relative calculation date
253
- * @param int $nth (optional) Number of matches to skip before returning
254
- * @param bool $invert (optional) Set to TRUE to go backwards in time
255
- * @param bool $allowCurrentDate (optional) Set to TRUE to return the
256
- * current date if it matches the cron expression
257
- *
258
- * @return DateTime
259
- * @throws RuntimeException on too many iterations
260
- */
261
- protected function getRunDate($currentTime = null, $nth = 0, $invert = false, $allowCurrentDate = false)
262
- {
263
- if ($currentTime instanceof DateTime) {
264
- $currentDate = $currentTime;
265
- } else {
266
- $currentDate = new DateTime($currentTime ? $currentTime : 'now');
267
- $currentDate->setTimezone(new DateTimeZone(date_default_timezone_get()));
268
- }
269
-
270
- $currentDate->setTime($currentDate->format('H'), $currentDate->format('i'), 0);
271
- $nextRun = clone $currentDate;
272
- $nth = (int) $nth;
273
-
274
- // Set a hard limit to bail on an impossible date
275
- for ($i = 0; $i < 1000; $i++) {
276
-
277
- foreach (self::$order as $position) {
278
- $part = $this->getExpression($position);
279
- if (null === $part) {
280
- continue;
281
- }
282
-
283
- $satisfied = false;
284
- // Get the field object used to validate this part
285
- $field = $this->fieldFactory->getField($position);
286
- // Check if this is singular or a list
287
- if (strpos($part, ',') === false) {
288
- $satisfied = $field->isSatisfiedBy($nextRun, $part);
289
- } else {
290
- foreach (array_map('trim', explode(',', $part)) as $listPart) {
291
- if ($field->isSatisfiedBy($nextRun, $listPart)) {
292
- $satisfied = true;
293
- break;
294
- }
295
- }
296
- }
297
-
298
- // If the field is not satisfied, then start over
299
- if (!$satisfied) {
300
- $field->increment($nextRun, $invert);
301
- continue 2;
302
- }
303
- }
304
-
305
- // Skip this match if needed
306
- if ((!$allowCurrentDate && $nextRun == $currentDate) || --$nth > -1) {
307
- $this->fieldFactory->getField(0)->increment($nextRun, $invert);
308
- continue;
309
- }
310
-
311
- return $nextRun;
312
- }
313
-
314
- // @codeCoverageIgnoreStart
315
- throw new RuntimeException('Impossible CRON expression');
316
- // @codeCoverageIgnoreEnd
317
- }
318
  }
13
  * @author Michael Dowling <mtdowling@gmail.com>
14
  * @link http://en.wikipedia.org/wiki/Cron
15
  */
16
+ class CronExpression {
17
+
18
+ const MINUTE = 0;
19
+ const HOUR = 1;
20
+ const DAY = 2;
21
+ const MONTH = 3;
22
+ const WEEKDAY = 4;
23
+ const YEAR = 5;
24
+
25
+ /**
26
+ * @var array CRON expression parts
27
+ */
28
+ private $cronParts;
29
+
30
+ /**
31
+ * @var CronExpression_FieldFactory CRON field factory
32
+ */
33
+ private $fieldFactory;
34
+
35
+ /**
36
+ * @var array Order in which to test of cron parts
37
+ */
38
+ private static $order = array( self::YEAR, self::MONTH, self::DAY, self::WEEKDAY, self::HOUR, self::MINUTE );
39
+
40
+ /**
41
+ * Factory method to create a new CronExpression.
42
+ *
43
+ * @param string $expression The CRON expression to create. There are
44
+ * several special predefined values which can be used to substitute the
45
+ * CRON expression:
46
+ *
47
+ * @yearly, @annually) - Run once a year, midnight, Jan. 1 - 0 0 1 1 *
48
+ * @monthly - Run once a month, midnight, first of month - 0 0 1 * *
49
+ * @weekly - Run once a week, midnight on Sun - 0 0 * * 0
50
+ * @daily - Run once a day, midnight - 0 0 * * *
51
+ * @hourly - Run once an hour, first minute - 0 * * * *
52
+ *
53
+ * @param CronExpression_FieldFactory $fieldFactory (optional) Field factory to use
54
+ *
55
+ * @return CronExpression
56
+ */
57
+ public static function factory( $expression, CronExpression_FieldFactory $fieldFactory = null ) {
58
+ $mappings = array(
59
+ '@yearly' => '0 0 1 1 *',
60
+ '@annually' => '0 0 1 1 *',
61
+ '@monthly' => '0 0 1 * *',
62
+ '@weekly' => '0 0 * * 0',
63
+ '@daily' => '0 0 * * *',
64
+ '@hourly' => '0 * * * *',
65
+ );
66
+
67
+ if ( isset( $mappings[ $expression ] ) ) {
68
+ $expression = $mappings[ $expression ];
69
+ }
70
+
71
+ return new self( $expression, $fieldFactory ? $fieldFactory : new CronExpression_FieldFactory() );
72
+ }
73
+
74
+ /**
75
+ * Parse a CRON expression
76
+ *
77
+ * @param string $expression CRON expression (e.g. '8 * * * *')
78
+ * @param CronExpression_FieldFactory $fieldFactory Factory to create cron fields
79
+ */
80
+ public function __construct( $expression, CronExpression_FieldFactory $fieldFactory ) {
81
+ $this->fieldFactory = $fieldFactory;
82
+ $this->setExpression( $expression );
83
+ }
84
+
85
+ /**
86
+ * Set or change the CRON expression
87
+ *
88
+ * @param string $value CRON expression (e.g. 8 * * * *)
89
+ *
90
+ * @return CronExpression
91
+ * @throws InvalidArgumentException if not a valid CRON expression
92
+ */
93
+ public function setExpression( $value ) {
94
+ $this->cronParts = preg_split( '/\s/', $value, -1, PREG_SPLIT_NO_EMPTY );
95
+ if ( count( $this->cronParts ) < 5 ) {
96
+ throw new InvalidArgumentException(
97
+ $value . ' is not a valid CRON expression'
98
+ );
99
+ }
100
+
101
+ foreach ( $this->cronParts as $position => $part ) {
102
+ $this->setPart( $position, $part );
103
+ }
104
+
105
+ return $this;
106
+ }
107
+
108
+ /**
109
+ * Set part of the CRON expression
110
+ *
111
+ * @param int $position The position of the CRON expression to set
112
+ * @param string $value The value to set
113
+ *
114
+ * @return CronExpression
115
+ * @throws InvalidArgumentException if the value is not valid for the part
116
+ */
117
+ public function setPart( $position, $value ) {
118
+ if ( ! $this->fieldFactory->getField( $position )->validate( $value ) ) {
119
+ throw new InvalidArgumentException(
120
+ 'Invalid CRON field value ' . $value . ' as position ' . $position
121
+ );
122
+ }
123
+
124
+ $this->cronParts[ $position ] = $value;
125
+
126
+ return $this;
127
+ }
128
+
129
+ /**
130
+ * Get a next run date relative to the current date or a specific date
131
+ *
132
+ * @param string|DateTime $currentTime (optional) Relative calculation date
133
+ * @param int $nth (optional) Number of matches to skip before returning a
134
+ * matching next run date. 0, the default, will return the current
135
+ * date and time if the next run date falls on the current date and
136
+ * time. Setting this value to 1 will skip the first match and go to
137
+ * the second match. Setting this value to 2 will skip the first 2
138
+ * matches and so on.
139
+ * @param bool $allowCurrentDate (optional) Set to TRUE to return the
140
+ * current date if it matches the cron expression
141
+ *
142
+ * @return DateTime
143
+ * @throws RuntimeException on too many iterations
144
+ */
145
+ public function getNextRunDate( $currentTime = 'now', $nth = 0, $allowCurrentDate = false ) {
146
+ return $this->getRunDate( $currentTime, $nth, false, $allowCurrentDate );
147
+ }
148
+
149
+ /**
150
+ * Get a previous run date relative to the current date or a specific date
151
+ *
152
+ * @param string|DateTime $currentTime (optional) Relative calculation date
153
+ * @param int $nth (optional) Number of matches to skip before returning
154
+ * @param bool $allowCurrentDate (optional) Set to TRUE to return the
155
+ * current date if it matches the cron expression
156
+ *
157
+ * @return DateTime
158
+ * @throws RuntimeException on too many iterations
159
+ * @see CronExpression::getNextRunDate
160
+ */
161
+ public function getPreviousRunDate( $currentTime = 'now', $nth = 0, $allowCurrentDate = false ) {
162
+ return $this->getRunDate( $currentTime, $nth, true, $allowCurrentDate );
163
+ }
164
+
165
+ /**
166
+ * Get multiple run dates starting at the current date or a specific date
167
+ *
168
+ * @param int $total Set the total number of dates to calculate
169
+ * @param string|DateTime $currentTime (optional) Relative calculation date
170
+ * @param bool $invert (optional) Set to TRUE to retrieve previous dates
171
+ * @param bool $allowCurrentDate (optional) Set to TRUE to return the
172
+ * current date if it matches the cron expression
173
+ *
174
+ * @return array Returns an array of run dates
175
+ */
176
+ public function getMultipleRunDates( $total, $currentTime = 'now', $invert = false, $allowCurrentDate = false ) {
177
+ $matches = array();
178
+ for ( $i = 0; $i < max( 0, $total ); $i++ ) {
179
+ $matches[] = $this->getRunDate( $currentTime, $i, $invert, $allowCurrentDate );
180
+ }
181
+
182
+ return $matches;
183
+ }
184
+
185
+ /**
186
+ * Get all or part of the CRON expression
187
+ *
188
+ * @param string $part (optional) Specify the part to retrieve or NULL to
189
+ * get the full cron schedule string.
190
+ *
191
+ * @return string|null Returns the CRON expression, a part of the
192
+ * CRON expression, or NULL if the part was specified but not found
193
+ */
194
+ public function getExpression( $part = null ) {
195
+ if ( null === $part ) {
196
+ return implode( ' ', $this->cronParts );
197
+ } elseif ( array_key_exists( $part, $this->cronParts ) ) {
198
+ return $this->cronParts[ $part ];
199
+ }
200
+
201
+ return null;
202
+ }
203
+
204
+ /**
205
+ * Helper method to output the full expression.
206
+ *
207
+ * @return string Full CRON expression
208
+ */
209
+ public function __toString() {
210
+ return $this->getExpression();
211
+ }
212
+
213
+ /**
214
+ * Determine if the cron is due to run based on the current date or a
215
+ * specific date. This method assumes that the current number of
216
+ * seconds are irrelevant, and should be called once per minute.
217
+ *
218
+ * @param string|DateTime $currentTime (optional) Relative calculation date
219
+ *
220
+ * @return bool Returns TRUE if the cron is due to run or FALSE if not
221
+ */
222
+ public function isDue( $currentTime = 'now' ) {
223
+ if ( 'now' === $currentTime ) {
224
+ $currentDate = date( 'Y-m-d H:i' );
225
+ $currentTime = strtotime( $currentDate );
226
+ } elseif ( $currentTime instanceof DateTime ) {
227
+ $currentDate = $currentTime->format( 'Y-m-d H:i' );
228
+ $currentTime = strtotime( $currentDate );
229
+ } else {
230
+ $currentTime = new DateTime( $currentTime );
231
+ $currentTime->setTime( $currentTime->format( 'H' ), $currentTime->format( 'i' ), 0 );
232
+ $currentDate = $currentTime->format( 'Y-m-d H:i' );
233
+ $currentTime = (int) ( $currentTime->getTimestamp() );
234
+ }
235
+
236
+ return $this->getNextRunDate( $currentDate, 0, true )->getTimestamp() == $currentTime;
237
+ }
238
+
239
+ /**
240
+ * Get the next or previous run date of the expression relative to a date
241
+ *
242
+ * @param string|DateTime $currentTime (optional) Relative calculation date
243
+ * @param int $nth (optional) Number of matches to skip before returning
244
+ * @param bool $invert (optional) Set to TRUE to go backwards in time
245
+ * @param bool $allowCurrentDate (optional) Set to TRUE to return the
246
+ * current date if it matches the cron expression
247
+ *
248
+ * @return DateTime
249
+ * @throws RuntimeException on too many iterations
250
+ */
251
+ protected function getRunDate( $currentTime = null, $nth = 0, $invert = false, $allowCurrentDate = false ) {
252
+ if ( $currentTime instanceof DateTime ) {
253
+ $currentDate = $currentTime;
254
+ } else {
255
+ $currentDate = new DateTime( $currentTime ? $currentTime : 'now' );
256
+ $currentDate->setTimezone( new DateTimeZone( date_default_timezone_get() ) );
257
+ }
258
+
259
+ $currentDate->setTime( $currentDate->format( 'H' ), $currentDate->format( 'i' ), 0 );
260
+ $nextRun = clone $currentDate;
261
+ $nth = (int) $nth;
262
+
263
+ // Set a hard limit to bail on an impossible date
264
+ for ( $i = 0; $i < 1000; $i++ ) {
265
+
266
+ foreach ( self::$order as $position ) {
267
+ $part = $this->getExpression( $position );
268
+ if ( null === $part ) {
269
+ continue;
270
+ }
271
+
272
+ $satisfied = false;
273
+ // Get the field object used to validate this part
274
+ $field = $this->fieldFactory->getField( $position );
275
+ // Check if this is singular or a list
276
+ if ( strpos( $part, ',' ) === false ) {
277
+ $satisfied = $field->isSatisfiedBy( $nextRun, $part );
278
+ } else {
279
+ foreach ( array_map( 'trim', explode( ',', $part ) ) as $listPart ) {
280
+ if ( $field->isSatisfiedBy( $nextRun, $listPart ) ) {
281
+ $satisfied = true;
282
+ break;
283
+ }
284
+ }
285
+ }
286
+
287
+ // If the field is not satisfied, then start over
288
+ if ( ! $satisfied ) {
289
+ $field->increment( $nextRun, $invert );
290
+ continue 2;
291
+ }
292
+ }
293
+
294
+ // Skip this match if needed
295
+ if ( ( ! $allowCurrentDate && $nextRun == $currentDate ) || --$nth > -1 ) {
296
+ $this->fieldFactory->getField( 0 )->increment( $nextRun, $invert );
297
+ continue;
298
+ }
299
+
300
+ return $nextRun;
301
+ }
302
+
303
+ // @codeCoverageIgnoreStart
304
+ throw new RuntimeException( 'Impossible CRON expression' );
305
+ // @codeCoverageIgnoreEnd
306
+ }
 
 
 
 
 
 
 
 
 
 
 
307
  }
lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_AbstractField.php CHANGED
@@ -5,96 +5,91 @@
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
- abstract class CronExpression_AbstractField implements CronExpression_FieldInterface
9
- {
10
- /**
11
- * Check to see if a field is satisfied by a value
12
- *
13
- * @param string $dateValue Date value to check
14
- * @param string $value Value to test
15
- *
16
- * @return bool
17
- */
18
- public function isSatisfied($dateValue, $value)
19
- {
20
- if ($this->isIncrementsOfRanges($value)) {
21
- return $this->isInIncrementsOfRanges($dateValue, $value);
22
- } elseif ($this->isRange($value)) {
23
- return $this->isInRange($dateValue, $value);
24
- }
25
 
26
- return $value == '*' || $dateValue == $value;
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- /**
30
- * Check if a value is a range
31
- *
32
- * @param string $value Value to test
33
- *
34
- * @return bool
35
- */
36
- public function isRange($value)
37
- {
38
- return strpos($value, '-') !== false;
39
- }
40
 
41
- /**
42
- * Check if a value is an increments of ranges
43
- *
44
- * @param string $value Value to test
45
- *
46
- * @return bool
47
- */
48
- public function isIncrementsOfRanges($value)
49
- {
50
- return strpos($value, '/') !== false;
51
- }
52
 
53
- /**
54
- * Test if a value is within a range
55
- *
56
- * @param string $dateValue Set date value
57
- * @param string $value Value to test
58
- *
59
- * @return bool
60
- */
61
- public function isInRange($dateValue, $value)
62
- {
63
- $parts = array_map('trim', explode('-', $value, 2));
64
 
65
- return $dateValue >= $parts[0] && $dateValue <= $parts[1];
66
- }
 
 
 
 
 
 
 
 
67
 
68
- /**
69
- * Test if a value is within an increments of ranges (offset[-to]/step size)
70
- *
71
- * @param string $dateValue Set date value
72
- * @param string $value Value to test
73
- *
74
- * @return bool
75
- */
76
- public function isInIncrementsOfRanges($dateValue, $value)
77
- {
78
- $parts = array_map('trim', explode('/', $value, 2));
79
- $stepSize = isset($parts[1]) ? $parts[1] : 0;
80
- if ($parts[0] == '*' || $parts[0] === '0') {
81
- return (int) $dateValue % $stepSize == 0;
82
- }
83
 
84
- $range = explode('-', $parts[0], 2);
85
- $offset = $range[0];
86
- $to = isset($range[1]) ? $range[1] : $dateValue;
87
- // Ensure that the date value is within the range
88
- if ($dateValue < $offset || $dateValue > $to) {
89
- return false;
90
- }
 
 
 
 
 
 
 
91
 
92
- for ($i = $offset; $i <= $to; $i+= $stepSize) {
93
- if ($i == $dateValue) {
94
- return true;
95
- }
96
- }
 
 
97
 
98
- return false;
99
- }
 
 
 
 
 
 
100
  }
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
+ abstract class CronExpression_AbstractField implements CronExpression_FieldInterface {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
+ /**
11
+ * Check to see if a field is satisfied by a value
12
+ *
13
+ * @param string $dateValue Date value to check
14
+ * @param string $value Value to test
15
+ *
16
+ * @return bool
17
+ */
18
+ public function isSatisfied( $dateValue, $value ) {
19
+ if ( $this->isIncrementsOfRanges( $value ) ) {
20
+ return $this->isInIncrementsOfRanges( $dateValue, $value );
21
+ } elseif ( $this->isRange( $value ) ) {
22
+ return $this->isInRange( $dateValue, $value );
23
+ }
24
 
25
+ return $value == '*' || $dateValue == $value;
26
+ }
 
 
 
 
 
 
 
 
 
27
 
28
+ /**
29
+ * Check if a value is a range
30
+ *
31
+ * @param string $value Value to test
32
+ *
33
+ * @return bool
34
+ */
35
+ public function isRange( $value ) {
36
+ return strpos( $value, '-' ) !== false;
37
+ }
 
38
 
39
+ /**
40
+ * Check if a value is an increments of ranges
41
+ *
42
+ * @param string $value Value to test
43
+ *
44
+ * @return bool
45
+ */
46
+ public function isIncrementsOfRanges( $value ) {
47
+ return strpos( $value, '/' ) !== false;
48
+ }
 
49
 
50
+ /**
51
+ * Test if a value is within a range
52
+ *
53
+ * @param string $dateValue Set date value
54
+ * @param string $value Value to test
55
+ *
56
+ * @return bool
57
+ */
58
+ public function isInRange( $dateValue, $value ) {
59
+ $parts = array_map( 'trim', explode( '-', $value, 2 ) );
60
 
61
+ return $dateValue >= $parts[0] && $dateValue <= $parts[1];
62
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
+ /**
65
+ * Test if a value is within an increments of ranges (offset[-to]/step size)
66
+ *
67
+ * @param string $dateValue Set date value
68
+ * @param string $value Value to test
69
+ *
70
+ * @return bool
71
+ */
72
+ public function isInIncrementsOfRanges( $dateValue, $value ) {
73
+ $parts = array_map( 'trim', explode( '/', $value, 2 ) );
74
+ $stepSize = isset( $parts[1] ) ? $parts[1] : 0;
75
+ if ( $parts[0] == '*' || $parts[0] === '0' ) {
76
+ return (int) $dateValue % $stepSize == 0;
77
+ }
78
 
79
+ $range = explode( '-', $parts[0], 2 );
80
+ $offset = $range[0];
81
+ $to = isset( $range[1] ) ? $range[1] : $dateValue;
82
+ // Ensure that the date value is within the range
83
+ if ( $dateValue < $offset || $dateValue > $to ) {
84
+ return false;
85
+ }
86
 
87
+ for ( $i = $offset; $i <= $to; $i += $stepSize ) {
88
+ if ( $i == $dateValue ) {
89
+ return true;
90
+ }
91
+ }
92
+
93
+ return false;
94
+ }
95
  }
lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_DayOfMonthField.php CHANGED
@@ -18,93 +18,89 @@
18
  *
19
  * @author Michael Dowling <mtdowling@gmail.com>
20
  */
21
- class CronExpression_DayOfMonthField extends CronExpression_AbstractField
22
- {
23
- /**
24
- * Get the nearest day of the week for a given day in a month
25
- *
26
- * @param int $currentYear Current year
27
- * @param int $currentMonth Current month
28
- * @param int $targetDay Target day of the month
29
- *
30
- * @return DateTime Returns the nearest date
31
- */
32
- private static function getNearestWeekday($currentYear, $currentMonth, $targetDay)
33
- {
34
- $tday = str_pad($targetDay, 2, '0', STR_PAD_LEFT);
35
- $target = new DateTime("$currentYear-$currentMonth-$tday");
36
- $currentWeekday = (int) $target->format('N');
37
 
38
- if ($currentWeekday < 6) {
39
- return $target;
40
- }
 
 
 
 
 
 
 
 
 
 
41
 
42
- $lastDayOfMonth = $target->format('t');
 
 
43
 
44
- foreach (array(-1, 1, -2, 2) as $i) {
45
- $adjusted = $targetDay + $i;
46
- if ($adjusted > 0 && $adjusted <= $lastDayOfMonth) {
47
- $target->setDate($currentYear, $currentMonth, $adjusted);
48
- if ($target->format('N') < 6 && $target->format('m') == $currentMonth) {
49
- return $target;
50
- }
51
- }
52
- }
53
- }
54
 
55
- /**
56
- * {@inheritdoc}
57
- */
58
- public function isSatisfiedBy(DateTime $date, $value)
59
- {
60
- // ? states that the field value is to be skipped
61
- if ($value == '?') {
62
- return true;
63
- }
 
64
 
65
- $fieldValue = $date->format('d');
 
 
 
 
 
 
 
66
 
67
- // Check to see if this is the last day of the month
68
- if ($value == 'L') {
69
- return $fieldValue == $date->format('t');
70
- }
71
 
72
- // Check to see if this is the nearest weekday to a particular value
73
- if (strpos($value, 'W')) {
74
- // Parse the target day
75
- $targetDay = substr($value, 0, strpos($value, 'W'));
76
- // Find out if the current day is the nearest day of the week
77
- return $date->format('j') == self::getNearestWeekday(
78
- $date->format('Y'),
79
- $date->format('m'),
80
- $targetDay
81
- )->format('j');
82
- }
83
 
84
- return $this->isSatisfied($date->format('d'), $value);
85
- }
 
 
 
 
 
 
 
 
 
86
 
87
- /**
88
- * {@inheritdoc}
89
- */
90
- public function increment(DateTime $date, $invert = false)
91
- {
92
- if ($invert) {
93
- $date->modify('previous day');
94
- $date->setTime(23, 59);
95
- } else {
96
- $date->modify('next day');
97
- $date->setTime(0, 0);
98
- }
99
 
100
- return $this;
101
- }
 
 
 
 
 
 
 
 
 
102
 
103
- /**
104
- * {@inheritdoc}
105
- */
106
- public function validate($value)
107
- {
108
- return (bool) preg_match('/[\*,\/\-\?LW0-9A-Za-z]+/', $value);
109
- }
 
 
110
  }
18
  *
19
  * @author Michael Dowling <mtdowling@gmail.com>
20
  */
21
+ class CronExpression_DayOfMonthField extends CronExpression_AbstractField {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ /**
24
+ * Get the nearest day of the week for a given day in a month
25
+ *
26
+ * @param int $currentYear Current year
27
+ * @param int $currentMonth Current month
28
+ * @param int $targetDay Target day of the month
29
+ *
30
+ * @return DateTime Returns the nearest date
31
+ */
32
+ private static function getNearestWeekday( $currentYear, $currentMonth, $targetDay ) {
33
+ $tday = str_pad( $targetDay, 2, '0', STR_PAD_LEFT );
34
+ $target = new DateTime( "$currentYear-$currentMonth-$tday" );
35
+ $currentWeekday = (int) $target->format( 'N' );
36
 
37
+ if ( $currentWeekday < 6 ) {
38
+ return $target;
39
+ }
40
 
41
+ $lastDayOfMonth = $target->format( 't' );
 
 
 
 
 
 
 
 
 
42
 
43
+ foreach ( array( -1, 1, -2, 2 ) as $i ) {
44
+ $adjusted = $targetDay + $i;
45
+ if ( $adjusted > 0 && $adjusted <= $lastDayOfMonth ) {
46
+ $target->setDate( $currentYear, $currentMonth, $adjusted );
47
+ if ( $target->format( 'N' ) < 6 && $target->format( 'm' ) == $currentMonth ) {
48
+ return $target;
49
+ }
50
+ }
51
+ }
52
+ }
53
 
54
+ /**
55
+ * {@inheritdoc}
56
+ */
57
+ public function isSatisfiedBy( DateTime $date, $value ) {
58
+ // ? states that the field value is to be skipped
59
+ if ( $value == '?' ) {
60
+ return true;
61
+ }
62
 
63
+ $fieldValue = $date->format( 'd' );
 
 
 
64
 
65
+ // Check to see if this is the last day of the month
66
+ if ( $value == 'L' ) {
67
+ return $fieldValue == $date->format( 't' );
68
+ }
 
 
 
 
 
 
 
69
 
70
+ // Check to see if this is the nearest weekday to a particular value
71
+ if ( strpos( $value, 'W' ) ) {
72
+ // Parse the target day
73
+ $targetDay = substr( $value, 0, strpos( $value, 'W' ) );
74
+ // Find out if the current day is the nearest day of the week
75
+ return $date->format( 'j' ) == self::getNearestWeekday(
76
+ $date->format( 'Y' ),
77
+ $date->format( 'm' ),
78
+ $targetDay
79
+ )->format( 'j' );
80
+ }
81
 
82
+ return $this->isSatisfied( $date->format( 'd' ), $value );
83
+ }
 
 
 
 
 
 
 
 
 
 
84
 
85
+ /**
86
+ * {@inheritdoc}
87
+ */
88
+ public function increment( DateTime $date, $invert = false ) {
89
+ if ( $invert ) {
90
+ $date->modify( 'previous day' );
91
+ $date->setTime( 23, 59 );
92
+ } else {
93
+ $date->modify( 'next day' );
94
+ $date->setTime( 0, 0 );
95
+ }
96
 
97
+ return $this;
98
+ }
99
+
100
+ /**
101
+ * {@inheritdoc}
102
+ */
103
+ public function validate( $value ) {
104
+ return (bool) preg_match( '/[\*,\/\-\?LW0-9A-Za-z]+/', $value );
105
+ }
106
  }
lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_DayOfWeekField.php CHANGED
@@ -15,110 +15,107 @@
15
  *
16
  * @author Michael Dowling <mtdowling@gmail.com>
17
  */
18
- class CronExpression_DayOfWeekField extends CronExpression_AbstractField
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- public function isSatisfiedBy(DateTime $date, $value)
24
- {
25
- if ($value == '?') {
26
- return true;
27
- }
28
 
29
- // Convert text day of the week values to integers
30
- $value = str_ireplace(
31
- array('SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'),
32
- range(0, 6),
33
- $value
34
- );
 
35
 
36
- $currentYear = $date->format('Y');
37
- $currentMonth = $date->format('m');
38
- $lastDayOfMonth = $date->format('t');
 
 
 
39
 
40
- // Find out if this is the last specific weekday of the month
41
- if (strpos($value, 'L')) {
42
- $weekday = str_replace('7', '0', substr($value, 0, strpos($value, 'L')));
43
- $tdate = clone $date;
44
- $tdate->setDate($currentYear, $currentMonth, $lastDayOfMonth);
45
- while ($tdate->format('w') != $weekday) {
46
- $tdate->setDate($currentYear, $currentMonth, --$lastDayOfMonth);
47
- }
48
 
49
- return $date->format('j') == $lastDayOfMonth;
50
- }
 
 
 
 
 
 
51
 
52
- // Handle # hash tokens
53
- if (strpos($value, '#')) {
54
- list($weekday, $nth) = explode('#', $value);
55
- // Validate the hash fields
56
- if ($weekday < 1 || $weekday > 5) {
57
- throw new InvalidArgumentException("Weekday must be a value between 1 and 5. {$weekday} given");
58
- }
59
- if ($nth > 5) {
60
- throw new InvalidArgumentException('There are never more than 5 of a given weekday in a month');
61
- }
62
- // The current weekday must match the targeted weekday to proceed
63
- if ($date->format('N') != $weekday) {
64
- return false;
65
- }
66
 
67
- $tdate = clone $date;
68
- $tdate->setDate($currentYear, $currentMonth, 1);
69
- $dayCount = 0;
70
- $currentDay = 1;
71
- while ($currentDay < $lastDayOfMonth + 1) {
72
- if ($tdate->format('N') == $weekday) {
73
- if (++$dayCount >= $nth) {
74
- break;
75
- }
76
- }
77
- $tdate->setDate($currentYear, $currentMonth, ++$currentDay);
78
- }
 
 
79
 
80
- return $date->format('j') == $currentDay;
81
- }
 
 
 
 
 
 
 
 
 
 
82
 
83
- // Handle day of the week values
84
- if (strpos($value, '-')) {
85
- $parts = explode('-', $value);
86
- if ($parts[0] == '7') {
87
- $parts[0] = '0';
88
- } elseif ($parts[1] == '0') {
89
- $parts[1] = '7';
90
- }
91
- $value = implode('-', $parts);
92
- }
93
 
94
- // Test to see which Sunday to use -- 0 == 7 == Sunday
95
- $format = in_array(7, str_split($value)) ? 'N' : 'w';
96
- $fieldValue = $date->format($format);
 
 
 
 
 
 
 
97
 
98
- return $this->isSatisfied($fieldValue, $value);
99
- }
 
100
 
101
- /**
102
- * {@inheritdoc}
103
- */
104
- public function increment(DateTime $date, $invert = false)
105
- {
106
- if ($invert) {
107
- $date->modify('-1 day');
108
- $date->setTime(23, 59, 0);
109
- } else {
110
- $date->modify('+1 day');
111
- $date->setTime(0, 0, 0);
112
- }
113
 
114
- return $this;
115
- }
 
 
 
 
 
 
 
 
 
116
 
117
- /**
118
- * {@inheritdoc}
119
- */
120
- public function validate($value)
121
- {
122
- return (bool) preg_match('/[\*,\/\-0-9A-Z]+/', $value);
123
- }
 
 
124
  }
15
  *
16
  * @author Michael Dowling <mtdowling@gmail.com>
17
  */
18
+ class CronExpression_DayOfWeekField extends CronExpression_AbstractField {
 
 
 
 
 
 
 
 
 
19
 
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ public function isSatisfiedBy( DateTime $date, $value ) {
24
+ if ( $value == '?' ) {
25
+ return true;
26
+ }
27
 
28
+ // Convert text day of the week values to integers
29
+ $value = str_ireplace(
30
+ array( 'SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT' ),
31
+ range( 0, 6 ),
32
+ $value
33
+ );
34
 
35
+ $currentYear = $date->format( 'Y' );
36
+ $currentMonth = $date->format( 'm' );
37
+ $lastDayOfMonth = $date->format( 't' );
 
 
 
 
 
38
 
39
+ // Find out if this is the last specific weekday of the month
40
+ if ( strpos( $value, 'L' ) ) {
41
+ $weekday = str_replace( '7', '0', substr( $value, 0, strpos( $value, 'L' ) ) );
42
+ $tdate = clone $date;
43
+ $tdate->setDate( $currentYear, $currentMonth, $lastDayOfMonth );
44
+ while ( $tdate->format( 'w' ) != $weekday ) {
45
+ $tdate->setDate( $currentYear, $currentMonth, --$lastDayOfMonth );
46
+ }
47
 
48
+ return $date->format( 'j' ) == $lastDayOfMonth;
49
+ }
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
+ // Handle # hash tokens
52
+ if ( strpos( $value, '#' ) ) {
53
+ list($weekday, $nth) = explode( '#', $value );
54
+ // Validate the hash fields
55
+ if ( $weekday < 1 || $weekday > 5 ) {
56
+ throw new InvalidArgumentException( "Weekday must be a value between 1 and 5. {$weekday} given" );
57
+ }
58
+ if ( $nth > 5 ) {
59
+ throw new InvalidArgumentException( 'There are never more than 5 of a given weekday in a month' );
60
+ }
61
+ // The current weekday must match the targeted weekday to proceed
62
+ if ( $date->format( 'N' ) != $weekday ) {
63
+ return false;
64
+ }
65
 
66
+ $tdate = clone $date;
67
+ $tdate->setDate( $currentYear, $currentMonth, 1 );
68
+ $dayCount = 0;
69
+ $currentDay = 1;
70
+ while ( $currentDay < $lastDayOfMonth + 1 ) {
71
+ if ( $tdate->format( 'N' ) == $weekday ) {
72
+ if ( ++$dayCount >= $nth ) {
73
+ break;
74
+ }
75
+ }
76
+ $tdate->setDate( $currentYear, $currentMonth, ++$currentDay );
77
+ }
78
 
79
+ return $date->format( 'j' ) == $currentDay;
80
+ }
 
 
 
 
 
 
 
 
81
 
82
+ // Handle day of the week values
83
+ if ( strpos( $value, '-' ) ) {
84
+ $parts = explode( '-', $value );
85
+ if ( $parts[0] == '7' ) {
86
+ $parts[0] = '0';
87
+ } elseif ( $parts[1] == '0' ) {
88
+ $parts[1] = '7';
89
+ }
90
+ $value = implode( '-', $parts );
91
+ }
92
 
93
+ // Test to see which Sunday to use -- 0 == 7 == Sunday
94
+ $format = in_array( 7, str_split( $value ) ) ? 'N' : 'w';
95
+ $fieldValue = $date->format( $format );
96
 
97
+ return $this->isSatisfied( $fieldValue, $value );
98
+ }
 
 
 
 
 
 
 
 
 
 
99
 
100
+ /**
101
+ * {@inheritdoc}
102
+ */
103
+ public function increment( DateTime $date, $invert = false ) {
104
+ if ( $invert ) {
105
+ $date->modify( '-1 day' );
106
+ $date->setTime( 23, 59, 0 );
107
+ } else {
108
+ $date->modify( '+1 day' );
109
+ $date->setTime( 0, 0, 0 );
110
+ }
111
 
112
+ return $this;
113
+ }
114
+
115
+ /**
116
+ * {@inheritdoc}
117
+ */
118
+ public function validate( $value ) {
119
+ return (bool) preg_match( '/[\*,\/\-0-9A-Z]+/', $value );
120
+ }
121
  }
lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_FieldFactory.php CHANGED
@@ -6,50 +6,49 @@
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  * @link http://en.wikipedia.org/wiki/Cron
8
  */
9
- class CronExpression_FieldFactory
10
- {
11
- /**
12
- * @var array Cache of instantiated fields
13
- */
14
- private $fields = array();
15
 
16
- /**
17
- * Get an instance of a field object for a cron expression position
18
- *
19
- * @param int $position CRON expression position value to retrieve
20
- *
21
- * @return CronExpression_FieldInterface
22
- * @throws InvalidArgumentException if a position is not valid
23
- */
24
- public function getField($position)
25
- {
26
- if (!isset($this->fields[$position])) {
27
- switch ($position) {
28
- case 0:
29
- $this->fields[$position] = new CronExpression_MinutesField();
30
- break;
31
- case 1:
32
- $this->fields[$position] = new CronExpression_HoursField();
33
- break;
34
- case 2:
35
- $this->fields[$position] = new CronExpression_DayOfMonthField();
36
- break;
37
- case 3:
38
- $this->fields[$position] = new CronExpression_MonthField();
39
- break;
40
- case 4:
41
- $this->fields[$position] = new CronExpression_DayOfWeekField();
42
- break;
43
- case 5:
44
- $this->fields[$position] = new CronExpression_YearField();
45
- break;
46
- default:
47
- throw new InvalidArgumentException(
48
- $position . ' is not a valid position'
49
- );
50
- }
51
- }
52
 
53
- return $this->fields[$position];
54
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  }
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  * @link http://en.wikipedia.org/wiki/Cron
8
  */
9
+ class CronExpression_FieldFactory {
 
 
 
 
 
10
 
11
+ /**
12
+ * @var array Cache of instantiated fields
13
+ */
14
+ private $fields = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ /**
17
+ * Get an instance of a field object for a cron expression position
18
+ *
19
+ * @param int $position CRON expression position value to retrieve
20
+ *
21
+ * @return CronExpression_FieldInterface
22
+ * @throws InvalidArgumentException if a position is not valid
23
+ */
24
+ public function getField( $position ) {
25
+ if ( ! isset( $this->fields[ $position ] ) ) {
26
+ switch ( $position ) {
27
+ case 0:
28
+ $this->fields[ $position ] = new CronExpression_MinutesField();
29
+ break;
30
+ case 1:
31
+ $this->fields[ $position ] = new CronExpression_HoursField();
32
+ break;
33
+ case 2:
34
+ $this->fields[ $position ] = new CronExpression_DayOfMonthField();
35
+ break;
36
+ case 3:
37
+ $this->fields[ $position ] = new CronExpression_MonthField();
38
+ break;
39
+ case 4:
40
+ $this->fields[ $position ] = new CronExpression_DayOfWeekField();
41
+ break;
42
+ case 5:
43
+ $this->fields[ $position ] = new CronExpression_YearField();
44
+ break;
45
+ default:
46
+ throw new InvalidArgumentException(
47
+ $position . ' is not a valid position'
48
+ );
49
+ }
50
+ }
51
+
52
+ return $this->fields[ $position ];
53
+ }
54
  }
lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_FieldInterface.php CHANGED
@@ -5,35 +5,35 @@
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
- interface CronExpression_FieldInterface
9
- {
10
- /**
11
- * Check if the respective value of a DateTime field satisfies a CRON exp
12
- *
13
- * @param DateTime $date DateTime object to check
14
- * @param string $value CRON expression to test against
15
- *
16
- * @return bool Returns TRUE if satisfied, FALSE otherwise
17
- */
18
- public function isSatisfiedBy(DateTime $date, $value);
19
 
20
- /**
21
- * When a CRON expression is not satisfied, this method is used to increment
22
- * or decrement a DateTime object by the unit of the cron field
23
- *
24
- * @param DateTime $date DateTime object to change
25
- * @param bool $invert (optional) Set to TRUE to decrement
26
- *
27
- * @return CronExpression_FieldInterface
28
- */
29
- public function increment(DateTime $date, $invert = false);
30
 
31
- /**
32
- * Validates a CRON expression for a given field
33
- *
34
- * @param string $value CRON expression value to validate
35
- *
36
- * @return bool Returns TRUE if valid, FALSE otherwise
37
- */
38
- public function validate($value);
 
 
 
 
 
 
 
 
 
 
 
39
  }
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
+ interface CronExpression_FieldInterface {
 
 
 
 
 
 
 
 
 
 
9
 
10
+ /**
11
+ * Check if the respective value of a DateTime field satisfies a CRON exp
12
+ *
13
+ * @param DateTime $date DateTime object to check
14
+ * @param string $value CRON expression to test against
15
+ *
16
+ * @return bool Returns TRUE if satisfied, FALSE otherwise
17
+ */
18
+ public function isSatisfiedBy( DateTime $date, $value);
 
19
 
20
+ /**
21
+ * When a CRON expression is not satisfied, this method is used to increment
22
+ * or decrement a DateTime object by the unit of the cron field
23
+ *
24
+ * @param DateTime $date DateTime object to change
25
+ * @param bool $invert (optional) Set to TRUE to decrement
26
+ *
27
+ * @return CronExpression_FieldInterface
28
+ */
29
+ public function increment( DateTime $date, $invert = false);
30
+
31
+ /**
32
+ * Validates a CRON expression for a given field
33
+ *
34
+ * @param string $value CRON expression value to validate
35
+ *
36
+ * @return bool Returns TRUE if valid, FALSE otherwise
37
+ */
38
+ public function validate( $value);
39
  }
lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_HoursField.php CHANGED
@@ -5,43 +5,40 @@
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
- class CronExpression_HoursField extends CronExpression_AbstractField
9
- {
10
- /**
11
- * {@inheritdoc}
12
- */
13
- public function isSatisfiedBy(DateTime $date, $value)
14
- {
15
- return $this->isSatisfied($date->format('H'), $value);
16
- }
17
 
18
- /**
19
- * {@inheritdoc}
20
- */
21
- public function increment(DateTime $date, $invert = false)
22
- {
23
- // Change timezone to UTC temporarily. This will
24
- // allow us to go back or forwards and hour even
25
- // if DST will be changed between the hours.
26
- $timezone = $date->getTimezone();
27
- $date->setTimezone(new DateTimeZone('UTC'));
28
- if ($invert) {
29
- $date->modify('-1 hour');
30
- $date->setTime($date->format('H'), 59);
31
- } else {
32
- $date->modify('+1 hour');
33
- $date->setTime($date->format('H'), 0);
34
- }
35
- $date->setTimezone($timezone);
36
 
37
- return $this;
38
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
- /**
41
- * {@inheritdoc}
42
- */
43
- public function validate($value)
44
- {
45
- return (bool) preg_match('/[\*,\/\-0-9]+/', $value);
46
- }
 
 
47
  }
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
+ class CronExpression_HoursField extends CronExpression_AbstractField {
 
 
 
 
 
 
 
 
9
 
10
+ /**
11
+ * {@inheritdoc}
12
+ */
13
+ public function isSatisfiedBy( DateTime $date, $value ) {
14
+ return $this->isSatisfied( $date->format( 'H' ), $value );
15
+ }
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ /**
18
+ * {@inheritdoc}
19
+ */
20
+ public function increment( DateTime $date, $invert = false ) {
21
+ // Change timezone to UTC temporarily. This will
22
+ // allow us to go back or forwards and hour even
23
+ // if DST will be changed between the hours.
24
+ $timezone = $date->getTimezone();
25
+ $date->setTimezone( new DateTimeZone( 'UTC' ) );
26
+ if ( $invert ) {
27
+ $date->modify( '-1 hour' );
28
+ $date->setTime( $date->format( 'H' ), 59 );
29
+ } else {
30
+ $date->modify( '+1 hour' );
31
+ $date->setTime( $date->format( 'H' ), 0 );
32
+ }
33
+ $date->setTimezone( $timezone );
34
 
35
+ return $this;
36
+ }
37
+
38
+ /**
39
+ * {@inheritdoc}
40
+ */
41
+ public function validate( $value ) {
42
+ return (bool) preg_match( '/[\*,\/\-0-9]+/', $value );
43
+ }
44
  }
lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_MinutesField.php CHANGED
@@ -5,35 +5,32 @@
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
- class CronExpression_MinutesField extends CronExpression_AbstractField
9
- {
10
- /**
11
- * {@inheritdoc}
12
- */
13
- public function isSatisfiedBy(DateTime $date, $value)
14
- {
15
- return $this->isSatisfied($date->format('i'), $value);
16
- }
17
 
18
- /**
19
- * {@inheritdoc}
20
- */
21
- public function increment(DateTime $date, $invert = false)
22
- {
23
- if ($invert) {
24
- $date->modify('-1 minute');
25
- } else {
26
- $date->modify('+1 minute');
27
- }
28
 
29
- return $this;
30
- }
 
 
 
 
 
 
 
31
 
32
- /**
33
- * {@inheritdoc}
34
- */
35
- public function validate($value)
36
- {
37
- return (bool) preg_match('/[\*,\/\-0-9]+/', $value);
38
- }
 
 
39
  }
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
+ class CronExpression_MinutesField extends CronExpression_AbstractField {
 
 
 
 
 
 
 
 
9
 
10
+ /**
11
+ * {@inheritdoc}
12
+ */
13
+ public function isSatisfiedBy( DateTime $date, $value ) {
14
+ return $this->isSatisfied( $date->format( 'i' ), $value );
15
+ }
 
 
 
 
16
 
17
+ /**
18
+ * {@inheritdoc}
19
+ */
20
+ public function increment( DateTime $date, $invert = false ) {
21
+ if ( $invert ) {
22
+ $date->modify( '-1 minute' );
23
+ } else {
24
+ $date->modify( '+1 minute' );
25
+ }
26
 
27
+ return $this;
28
+ }
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ public function validate( $value ) {
34
+ return (bool) preg_match( '/[\*,\/\-0-9]+/', $value );
35
+ }
36
  }
lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_MonthField.php CHANGED
@@ -5,51 +5,58 @@
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
- class CronExpression_MonthField extends CronExpression_AbstractField
9
- {
10
- /**
11
- * {@inheritdoc}
12
- */
13
- public function isSatisfiedBy(DateTime $date, $value)
14
- {
15
- // Convert text month values to integers
16
- $value = str_ireplace(
17
- array(
18
- 'JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN',
19
- 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'
20
- ),
21
- range(1, 12),
22
- $value
23
- );
24
 
25
- return $this->isSatisfied($date->format('m'), $value);
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
- /**
29
- * {@inheritdoc}
30
- */
31
- public function increment(DateTime $date, $invert = false)
32
- {
33
- if ($invert) {
34
- // $date->modify('last day of previous month'); // remove for php 5.2 compat
35
- $date->modify('previous month');
36
- $date->modify($date->format('Y-m-t'));
37
- $date->setTime(23, 59);
38
- } else {
39
- //$date->modify('first day of next month'); // remove for php 5.2 compat
40
- $date->modify('next month');
41
- $date->modify($date->format('Y-m-01'));
42
- $date->setTime(0, 0);
43
- }
44
 
45
- return $this;
46
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
- /**
49
- * {@inheritdoc}
50
- */
51
- public function validate($value)
52
- {
53
- return (bool) preg_match('/[\*,\/\-0-9A-Z]+/', $value);
54
- }
 
 
55
  }
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
+ class CronExpression_MonthField extends CronExpression_AbstractField {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
+ /**
11
+ * {@inheritdoc}
12
+ */
13
+ public function isSatisfiedBy( DateTime $date, $value ) {
14
+ // Convert text month values to integers
15
+ $value = str_ireplace(
16
+ array(
17
+ 'JAN',
18
+ 'FEB',
19
+ 'MAR',
20
+ 'APR',
21
+ 'MAY',
22
+ 'JUN',
23
+ 'JUL',
24
+ 'AUG',
25
+ 'SEP',
26
+ 'OCT',
27
+ 'NOV',
28
+ 'DEC',
29
+ ),
30
+ range( 1, 12 ),
31
+ $value
32
+ );
33
 
34
+ return $this->isSatisfied( $date->format( 'm' ), $value );
35
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
+ /**
38
+ * {@inheritdoc}
39
+ */
40
+ public function increment( DateTime $date, $invert = false ) {
41
+ if ( $invert ) {
42
+ // $date->modify('last day of previous month'); // remove for php 5.2 compat
43
+ $date->modify( 'previous month' );
44
+ $date->modify( $date->format( 'Y-m-t' ) );
45
+ $date->setTime( 23, 59 );
46
+ } else {
47
+ // $date->modify('first day of next month'); // remove for php 5.2 compat
48
+ $date->modify( 'next month' );
49
+ $date->modify( $date->format( 'Y-m-01' ) );
50
+ $date->setTime( 0, 0 );
51
+ }
52
 
53
+ return $this;
54
+ }
55
+
56
+ /**
57
+ * {@inheritdoc}
58
+ */
59
+ public function validate( $value ) {
60
+ return (bool) preg_match( '/[\*,\/\-0-9A-Z]+/', $value );
61
+ }
62
  }
lite/includes/libraries/action-scheduler/lib/cron-expression/CronExpression_YearField.php CHANGED
@@ -5,39 +5,36 @@
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
- class CronExpression_YearField extends CronExpression_AbstractField
9
- {
10
- /**
11
- * {@inheritdoc}
12
- */
13
- public function isSatisfiedBy(DateTime $date, $value)
14
- {
15
- return $this->isSatisfied($date->format('Y'), $value);
16
- }
17
 
18
- /**
19
- * {@inheritdoc}
20
- */
21
- public function increment(DateTime $date, $invert = false)
22
- {
23
- if ($invert) {
24
- $date->modify('-1 year');
25
- $date->setDate($date->format('Y'), 12, 31);
26
- $date->setTime(23, 59, 0);
27
- } else {
28
- $date->modify('+1 year');
29
- $date->setDate($date->format('Y'), 1, 1);
30
- $date->setTime(0, 0, 0);
31
- }
32
 
33
- return $this;
34
- }
 
 
 
 
 
 
 
 
 
 
 
35
 
36
- /**
37
- * {@inheritdoc}
38
- */
39
- public function validate($value)
40
- {
41
- return (bool) preg_match('/[\*,\/\-0-9]+/', $value);
42
- }
 
 
43
  }
5
  *
6
  * @author Michael Dowling <mtdowling@gmail.com>
7
  */
8
+ class CronExpression_YearField extends CronExpression_AbstractField {
 
 
 
 
 
 
 
 
9
 
10
+ /**
11
+ * {@inheritdoc}
12
+ */
13
+ public function isSatisfiedBy( DateTime $date, $value ) {
14
+ return $this->isSatisfied( $date->format( 'Y' ), $value );
15
+ }
 
 
 
 
 
 
 
 
16
 
17
+ /**
18
+ * {@inheritdoc}
19
+ */
20
+ public function increment( DateTime $date, $invert = false ) {
21
+ if ( $invert ) {
22
+ $date->modify( '-1 year' );
23
+ $date->setDate( $date->format( 'Y' ), 12, 31 );
24
+ $date->setTime( 23, 59, 0 );
25
+ } else {
26
+ $date->modify( '+1 year' );
27
+ $date->setDate( $date->format( 'Y' ), 1, 1 );
28
+ $date->setTime( 0, 0, 0 );
29
+ }
30
 
31
+ return $this;
32
+ }
33
+
34
+ /**
35
+ * {@inheritdoc}
36
+ */
37
+ public function validate( $value ) {
38
+ return (bool) preg_match( '/[\*,\/\-0-9]+/', $value );
39
+ }
40
  }
lite/includes/libraries/class-es-html2text.php CHANGED
@@ -195,9 +195,9 @@ class ES_Html2Text {
195
  // 'table' (if a table of link URLs should be listed after the text.
196
  // 'bbcode' (show links as bbcode)
197
 
198
- 'width' => 70, // Maximum width of the formatted text, in columns.
199
- // Set this value to 0 (or less) to ignore word wrapping
200
- // and not constrain text to a fixed-width column.
201
  );
202
 
203
  /**
@@ -216,8 +216,8 @@ class ES_Html2Text {
216
  /**
217
  * Class constructor
218
  *
219
- * @param string $html (optional) Source HTML
220
- * @param array $options (optional) Set configuration options
221
  * @return unknown
222
  */
223
  public function __construct( $html = '', $options = array() ) {
@@ -227,14 +227,14 @@ class ES_Html2Text {
227
  * By taking the copy early this is avoided. This behavior changed in PHP7: [https://www.php.net/manual/en/function.func-get-args.php#refsect1-function.func-get-args-notes]
228
  */
229
  $func_args = func_get_args();
230
-
231
  // for backwards compatibility
232
  if ( ! is_array( $options ) ) {
233
  return call_user_func_array( array( $this, 'legacyConstruct' ), $func_args );
234
  }
235
 
236
- $this->html = $html;
237
- $this->options = array_merge( $this->options, $options );
238
  $this->htmlFuncFlags = ( PHP_VERSION_ID < 50400 )
239
  ? ENT_COMPAT
240
  : ENT_COMPAT | ENT_HTML5;
@@ -254,10 +254,10 @@ class ES_Html2Text {
254
  /**
255
  * Set the source HTML
256
  *
257
- * @param string $html HTML source content
258
  */
259
  public function setHtml( $html ) {
260
- $this->html = $html;
261
  $this->converted = false;
262
  }
263
 
@@ -285,7 +285,7 @@ class ES_Html2Text {
285
  * @return string
286
  */
287
  public function getText() {
288
- if ( !$this->converted ) {
289
  $this->convert();
290
  }
291
 
@@ -328,7 +328,7 @@ class ES_Html2Text {
328
  /**
329
  * Sets a base URL to handle relative links.
330
  *
331
- * @param string $baseurl
332
  */
333
  public function setBaseUrl( $baseurl ) {
334
  $this->baseurl = $baseurl;
@@ -423,9 +423,9 @@ class ES_Html2Text {
423
  * appeared. Also makes an effort at identifying and handling absolute
424
  * and relative links.
425
  *
426
- * @param string $link URL of the link
427
- * @param string $display Part of the text to associate number with
428
- * @param null $linkOverride
429
  * @return string
430
  */
431
  protected function buildlinkList( $link, $display, $linkOverride = null ) {
@@ -452,7 +452,7 @@ class ES_Html2Text {
452
  if ( 'table' == $linkMethod ) {
453
  $index = array_search( $url, $this->linkList );
454
  if ( false === $index ) {
455
- $index = count( $this->linkList );
456
  $this->linkList[] = $url;
457
  }
458
 
@@ -509,15 +509,15 @@ class ES_Html2Text {
509
  /**
510
  * Helper function for BLOCKQUOTE body conversion.
511
  *
512
- * @param string $text (reference) HTML content
513
  */
514
  protected function convertBlockquotes( &$text ) {
515
  if ( preg_match_all( '/<\/*blockquote[^>]*>/i', $text, $matches, PREG_OFFSET_CAPTURE ) ) {
516
  $originalText = $text;
517
- $start = 0;
518
- $taglen = 0;
519
- $level = 0;
520
- $diff = 0;
521
  foreach ( $matches[0] as $m ) {
522
  $m[1] = strlen( substr( $originalText, 0, $m[1] ) );
523
  if ( '<' == $m[0][0] && '/' == $m[0][1] ) {
@@ -554,7 +554,7 @@ class ES_Html2Text {
554
  }
555
  } else {
556
  if ( 0 == $level ) {
557
- $start = $m[1];
558
  $taglen = strlen( $m[0] );
559
  }
560
  $level++;
@@ -567,7 +567,7 @@ class ES_Html2Text {
567
  /**
568
  * Callback function for preg_replace_callback use.
569
  *
570
- * @param array $matches PREG matches
571
  * @return string
572
  */
573
  protected function pregCallback( $matches ) {
@@ -609,7 +609,7 @@ class ES_Html2Text {
609
  /**
610
  * Callback function for preg_replace_callback use in PRE content handler.
611
  *
612
- * @param array $matches PREG matches
613
  * @return string
614
  */
615
  protected function pregPreCallback( $matches ) {
@@ -620,7 +620,7 @@ class ES_Html2Text {
620
  /**
621
  * Strtoupper function with HTML tags and entities handling.
622
  *
623
- * @param string $str Text to convert
624
  * @return string Converted text
625
  */
626
  protected function toupper( $str ) {
@@ -629,8 +629,8 @@ class ES_Html2Text {
629
 
630
  // convert toupper only the text between HTML tags
631
  foreach ( $chunks as $i => $chunk ) {
632
- if ( '<' != $chunk[0] ) {
633
- $chunks[$i] = $this->strtoupper( $chunk );
634
  }
635
  }
636
 
@@ -641,7 +641,7 @@ class ES_Html2Text {
641
  /**
642
  * Strtoupper multibyte wrapper function with HTML entities handling.
643
  *
644
- * @param string $str Text to convert
645
  * @return string Converted text
646
  */
647
  protected function strtoupper( $str ) {
195
  // 'table' (if a table of link URLs should be listed after the text.
196
  // 'bbcode' (show links as bbcode)
197
 
198
+ 'width' => 70, // Maximum width of the formatted text, in columns.
199
+ // Set this value to 0 (or less) to ignore word wrapping
200
+ // and not constrain text to a fixed-width column.
201
  );
202
 
203
  /**
216
  /**
217
  * Class constructor
218
  *
219
+ * @param string $html (optional) Source HTML
220
+ * @param array $options (optional) Set configuration options
221
  * @return unknown
222
  */
223
  public function __construct( $html = '', $options = array() ) {
227
  * By taking the copy early this is avoided. This behavior changed in PHP7: [https://www.php.net/manual/en/function.func-get-args.php#refsect1-function.func-get-args-notes]
228
  */
229
  $func_args = func_get_args();
230
+
231
  // for backwards compatibility
232
  if ( ! is_array( $options ) ) {
233
  return call_user_func_array( array( $this, 'legacyConstruct' ), $func_args );
234
  }
235
 
236
+ $this->html = $html;
237
+ $this->options = array_merge( $this->options, $options );
238
  $this->htmlFuncFlags = ( PHP_VERSION_ID < 50400 )
239
  ? ENT_COMPAT
240
  : ENT_COMPAT | ENT_HTML5;
254
  /**
255
  * Set the source HTML
256
  *
257
+ * @param string $html HTML source content
258
  */
259
  public function setHtml( $html ) {
260
+ $this->html = $html;
261
  $this->converted = false;
262
  }
263
 
285
  * @return string
286
  */
287
  public function getText() {
288
+ if ( ! $this->converted ) {
289
  $this->convert();
290
  }
291
 
328
  /**
329
  * Sets a base URL to handle relative links.
330
  *
331
+ * @param string $baseurl
332
  */
333
  public function setBaseUrl( $baseurl ) {
334
  $this->baseurl = $baseurl;
423
  * appeared. Also makes an effort at identifying and handling absolute
424
  * and relative links.
425
  *
426
+ * @param string $link URL of the link
427
+ * @param string $display Part of the text to associate number with
428
+ * @param null $linkOverride
429
  * @return string
430
  */
431
  protected function buildlinkList( $link, $display, $linkOverride = null ) {
452
  if ( 'table' == $linkMethod ) {
453
  $index = array_search( $url, $this->linkList );
454
  if ( false === $index ) {
455
+ $index = count( $this->linkList );
456
  $this->linkList[] = $url;
457
  }
458
 
509
  /**
510
  * Helper function for BLOCKQUOTE body conversion.
511
  *
512
+ * @param string $text (reference) HTML content
513
  */
514
  protected function convertBlockquotes( &$text ) {
515
  if ( preg_match_all( '/<\/*blockquote[^>]*>/i', $text, $matches, PREG_OFFSET_CAPTURE ) ) {
516
  $originalText = $text;
517
+ $start = 0;
518
+ $taglen = 0;
519
+ $level = 0;
520
+ $diff = 0;
521
  foreach ( $matches[0] as $m ) {
522
  $m[1] = strlen( substr( $originalText, 0, $m[1] ) );
523
  if ( '<' == $m[0][0] && '/' == $m[0][1] ) {
554
  }
555
  } else {
556
  if ( 0 == $level ) {
557
+ $start = $m[1];
558
  $taglen = strlen( $m[0] );
559
  }
560
  $level++;
567
  /**
568
  * Callback function for preg_replace_callback use.
569
  *
570
+ * @param array $matches PREG matches
571
  * @return string
572
  */
573
  protected function pregCallback( $matches ) {
609
  /**
610
  * Callback function for preg_replace_callback use in PRE content handler.
611
  *
612
+ * @param array $matches PREG matches
613
  * @return string
614
  */
615
  protected function pregPreCallback( $matches ) {
620
  /**
621
  * Strtoupper function with HTML tags and entities handling.
622
  *
623
+ * @param string $str Text to convert
624
  * @return string Converted text
625
  */
626
  protected function toupper( $str ) {
629
 
630
  // convert toupper only the text between HTML tags
631
  foreach ( $chunks as $i => $chunk ) {
632
+ if ( '<' != $chunk[0] ) {
633
+ $chunks[ $i ] = $this->strtoupper( $chunk );
634
  }
635
  }
636
 
641
  /**
642
  * Strtoupper multibyte wrapper function with HTML entities handling.
643
  *
644
+ * @param string $str Text to convert
645
  * @return string Converted text
646
  */
647
  protected function strtoupper( $str ) {
lite/includes/libraries/wp-js-editor/wp-js-editor.php CHANGED
@@ -1,52 +1,52 @@
1
- <?php
2
-
3
- /**
4
- * Function to load required html/js for creating WP Editor dynamically.
5
- *
6
- * @since 4.4.1
7
- */
8
- function ig_es_wp_js_editor_load_scripts() {
9
-
10
- if ( ! class_exists( '_WP_Editors' ) ) {
11
- require( ABSPATH . WPINC . '/class-wp-editor.php' );
12
- }
13
-
14
- $editor_args = array(
15
- 'textarea_rows' => 40,
16
- 'editor_class' => 'wp-editor-content',
17
- 'media_buttons' => true,
18
- 'tinymce' => true,
19
- 'quicktags' => true,
20
- );
21
- ?>
22
- <script id="_wp-mce-editor-tpl" type="text/html">
23
- <?php wp_editor( '', '__wp_mce_editor__', $editor_args ); ?>
24
- </script>
25
- <?php
26
- wp_enqueue_script( 'ig_es_wp_js_editor', plugin_dir_url( __FILE__ ) . 'wp-js-editor.js', array( 'jquery' ), '1.0.0', true );
27
- }
28
-
29
- /**
30
- * Load html/js in admin area.
31
- *
32
- * @since 4.4.1
33
- */
34
- function ig_es_wp_js_editor_admin_scripts() {
35
- if ( is_admin() ) {
36
- add_action( 'admin_footer', 'ig_es_wp_js_editor_load_scripts', -1 );
37
- }
38
- }
39
-
40
- /**
41
- * Load html/js in frontend area.
42
- *
43
- * @since 4.4.1
44
- */
45
- function ig_es_wp_js_editor_frontend_scripts() {
46
- if ( ! is_admin() ) {
47
- add_action( 'wp_footer', 'ig_es_wp_js_editor_load_scripts', -1 );
48
- }
49
- }
50
-
51
-
52
-
1
+ <?php
2
+
3
+ /**
4
+ * Function to load required html/js for creating WP Editor dynamically.
5
+ *
6
+ * @since 4.4.1
7
+ */
8
+ function ig_es_wp_js_editor_load_scripts() {
9
+
10
+ if ( ! class_exists( '_WP_Editors' ) ) {
11
+ require ABSPATH . WPINC . '/class-wp-editor.php';
12
+ }
13
+
14
+ $editor_args = array(
15
+ 'textarea_rows' => 40,
16
+ 'editor_class' => 'wp-editor-content',
17
+ 'media_buttons' => true,
18
+ 'tinymce' => true,
19
+ 'quicktags' => true,
20
+ );
21
+ ?>
22
+ <script id="_wp-mce-editor-tpl" type="text/html">
23
+ <?php wp_editor( '', '__wp_mce_editor__', $editor_args ); ?>
24
+ </script>
25
+ <?php
26
+ wp_enqueue_script( 'ig_es_wp_js_editor', plugin_dir_url( __FILE__ ) . 'wp-js-editor.js', array( 'jquery' ), '1.0.0', true );
27
+ }
28
+
29
+ /**
30
+ * Load html/js in admin area.
31
+ *
32
+ * @since 4.4.1
33
+ */
34
+ function ig_es_wp_js_editor_admin_scripts() {
35
+ if ( is_admin() ) {
36
+ add_action( 'admin_footer', 'ig_es_wp_js_editor_load_scripts', -1 );
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Load html/js in frontend area.
42
+ *
43
+ * @since 4.4.1
44
+ */
45
+ function ig_es_wp_js_editor_frontend_scripts() {
46
+ if ( ! is_admin() ) {
47
+ add_action( 'wp_footer', 'ig_es_wp_js_editor_load_scripts', -1 );
48
+ }
49
+ }
50
+
51
+
52
+
lite/includes/logs/class-ig-log-handler-interface.php CHANGED
@@ -12,17 +12,16 @@ if ( ! interface_exists( 'IG_Log_Handler_Interface' ) ) {
12
  * ES Log Handler Interface
13
  *
14
  * Functions that must be defined to correctly fulfill log handler API.
15
- *
16
  */
17
  interface IG_Log_Handler_Interface {
18
 
19
  /**
20
  * Handle a log entry.
21
  *
22
- * @param int $timestamp Log timestamp.
23
  * @param string $level emergency|alert|critical|error|warning|notice|info|debug.
24
  * @param string $message Log message.
25
- * @param array $context Additional information for log handlers.
26
  *
27
  * @return bool False if value was not handled and true if value was handled.
28
  */
12
  * ES Log Handler Interface
13
  *
14
  * Functions that must be defined to correctly fulfill log handler API.
 
15
  */
16
  interface IG_Log_Handler_Interface {
17
 
18
  /**
19
  * Handle a log entry.
20
  *
21
+ * @param int $timestamp Log timestamp.
22
  * @param string $level emergency|alert|critical|error|warning|notice|info|debug.
23
  * @param string $message Log message.
24
+ * @param array $context Additional information for log handlers.
25
  *
26
  * @return bool False if value was not handled and true if value was handled.
27
  */
lite/includes/logs/class-ig-log-handler.php CHANGED
@@ -29,10 +29,10 @@ if ( ! class_exists( 'IG_Log_Handler' ) ) {
29
  /**
30
  * Builds a log entry text from level, timestamp and message.
31
  *
32
- * @param int $timestamp Log timestamp.
33
  * @param string $level emergency|alert|critical|error|warning|notice|info|debug.
34
  * @param string $message Log message.
35
- * @param array $context Additional information for log handlers.
36
  *
37
  * @return string Formatted log entry.
38
  */
@@ -41,12 +41,16 @@ if ( ! class_exists( 'IG_Log_Handler' ) ) {
41
  $level_string = strtoupper( $level );
42
  $entry = "{$time_string} {$level_string} {$message}";
43
 
44
- return apply_filters( 'ig_format_log_entry', $entry, array(
45
- 'timestamp' => $timestamp,
46
- 'level' => $level,
47
- 'message' => $message,
48
- 'context' => $context,
49
- ) );
 
 
 
 
50
  }
51
  }
52
  }
29
  /**
30
  * Builds a log entry text from level, timestamp and message.
31
  *
32
+ * @param int $timestamp Log timestamp.
33
  * @param string $level emergency|alert|critical|error|warning|notice|info|debug.
34
  * @param string $message Log message.
35
+ * @param array $context Additional information for log handlers.
36
  *
37
  * @return string Formatted log entry.
38
  */
41
  $level_string = strtoupper( $level );
42
  $entry = "{$time_string} {$level_string} {$message}";
43
 
44
+ return apply_filters(
45
+ 'ig_format_log_entry',
46
+ $entry,
47
+ array(
48
+ 'timestamp' => $timestamp,
49
+ 'level' => $level,
50
+ 'message' => $message,
51
+ 'context' => $context,
52
+ )
53
+ );
54
  }
55
  }
56
  }
lite/includes/logs/class-ig-logger-interface.php CHANGED
@@ -1,8 +1,6 @@
1
  <?php
2
  /**
3
  * Logger Interface
4
- *
5
- *
6
  */
7
  if ( ! defined( 'ABSPATH' ) ) {
8
  exit; // Exit if accessed directly.
@@ -46,7 +44,7 @@ if ( ! interface_exists( 'IG_Logger_Interface' ) ) {
46
  * 'info': Informational messages.
47
  * 'debug': Debug-level messages.
48
  * @param string $message Log message.
49
- * @param array $context Optional. Additional information for log handlers.
50
  */
51
  public function log( $level, $message, $context = array() );
52
 
@@ -56,7 +54,7 @@ if ( ! interface_exists( 'IG_Logger_Interface' ) ) {
56
  * System is unusable.
57
  *
58
  * @param string $message Log message.
59
- * @param array $context Optional. Additional information for log handlers.
60
  */
61
  public function emergency( $message, $context = array() );
62
 
@@ -67,7 +65,7 @@ if ( ! interface_exists( 'IG_Logger_Interface' ) ) {
67
  * Example: Entire website down, database unavailable, etc.
68
  *
69
  * @param string $message Log message.
70
- * @param array $context Optional. Additional information for log handlers.
71
  */
72
  public function alert( $message, $context = array() );
73
 
@@ -78,7 +76,7 @@ if ( ! interface_exists( 'IG_Logger_Interface' ) ) {
78
  * Example: Application component unavailable, unexpected exception.
79
  *
80
  * @param string $message Log message.
81
- * @param array $context Optional. Additional information for log handlers.
82
  */
83
  public function critical( $message, $context = array() );
84
 
@@ -89,7 +87,7 @@ if ( ! interface_exists( 'IG_Logger_Interface' ) ) {
89
  * and monitored.
90
  *
91
  * @param string $message Log message.
92
- * @param array $context Optional. Additional information for log handlers.
93
  */
94
  public function error( $message, $context = array() );
95
 
@@ -102,7 +100,7 @@ if ( ! interface_exists( 'IG_Logger_Interface' ) ) {
102
  * necessarily wrong.
103
  *
104
  * @param string $message Log message.
105
- * @param array $context Optional. Additional information for log handlers.
106
  */
107
  public function warning( $message, $context = array() );
108
 
@@ -112,7 +110,7 @@ if ( ! interface_exists( 'IG_Logger_Interface' ) ) {
112
  * Normal but significant events.
113
  *
114
  * @param string $message Log message.
115
- * @param array $context Optional. Additional information for log handlers.
116
  */
117
  public function notice( $message, $context = array() );
118
 
@@ -123,7 +121,7 @@ if ( ! interface_exists( 'IG_Logger_Interface' ) ) {
123
  * Example: User logs in, SQL logs.
124
  *
125
  * @param string $message Log message.
126
- * @param array $context Optional. Additional information for log handlers.
127
  */
128
  public function info( $message, $context = array() );
129
 
@@ -133,7 +131,7 @@ if ( ! interface_exists( 'IG_Logger_Interface' ) ) {
133
  * Detailed debug information.
134
  *
135
  * @param string $message Log message.
136
- * @param array $context Optional. Additional information for log handlers.
137
  */
138
  public function debug( $message, $context = array() );
139
  }
1
  <?php
2
  /**
3
  * Logger Interface
 
 
4
  */
5
  if ( ! defined( 'ABSPATH' ) ) {
6
  exit; // Exit if accessed directly.
44
  * 'info': Informational messages.
45
  * 'debug': Debug-level messages.
46
  * @param string $message Log message.
47
+ * @param array $context Optional. Additional information for log handlers.
48
  */
49
  public function log( $level, $message, $context = array() );
50
 
54
  * System is unusable.
55
  *
56
  * @param string $message Log message.
57
+ * @param array $context Optional. Additional information for log handlers.
58
  */
59
  public function emergency( $message, $context = array() );
60
 
65
  * Example: Entire website down, database unavailable, etc.
66
  *
67
  * @param string $message Log message.
68
+ * @param array $context Optional. Additional information for log handlers.
69
  */
70
  public function alert( $message, $context = array() );
71
 
76
  * Example: Application component unavailable, unexpected exception.
77
  *
78
  * @param string $message Log message.
79
+ * @param array $context Optional. Additional information for log handlers.
80
  */
81
  public function critical( $message, $context = array() );
82
 
87
  * and monitored.
88
  *
89
  * @param string $message Log message.
90
+ * @param array $context Optional. Additional information for log handlers.
91
  */
92
  public function error( $message, $context = array() );
93
 
100
  * necessarily wrong.
101
  *
102
  * @param string $message Log message.
103
+ * @param array $context Optional. Additional information for log handlers.
104
  */
105
  public function warning( $message, $context = array() );
106
 
110
  * Normal but significant events.
111
  *
112
  * @param string $message Log message.
113
+ * @param array $context Optional. Additional information for log handlers.
114
  */
115
  public function notice( $message, $context = array() );
116
 
121
  * Example: User logs in, SQL logs.
122
  *
123
  * @param string $message Log message.
124
+ * @param array $context Optional. Additional information for log handlers.
125
  */
126
  public function info( $message, $context = array() );
127
 
131
  * Detailed debug information.
132
  *
133
  * @param string $message Log message.
134
+ * @param array $context Optional. Additional information for log handlers.
135
  */
136
  public function debug( $message, $context = array() );
137
  }
lite/includes/logs/log-handlers/class-ig-log-handler-file.php CHANGED
@@ -79,10 +79,10 @@ if ( ! class_exists( 'IG_Log_Handler_File' ) ) {
79
  /**
80
  * Builds a log entry text from timestamp, level and message.
81
  *
82
- * @param int $timestamp Log timestamp.
83
  * @param string $level emergency|alert|critical|error|warning|notice|info|debug.
84
  * @param string $message Log message.
85
- * @param array $context Additional information for log handlers.
86
  *
87
  * @return string Formatted log entry.
88
  */
@@ -275,7 +275,7 @@ if ( ! class_exists( 'IG_Log_Handler_File' ) ) {
275
  /**
276
  * Increment a log file suffix.
277
  *
278
- * @param string $handle Log handle.
279
  * @param null|int $number Optional. Default null. Log suffix number to be incremented.
280
  *
281
  * @return bool True if increment was successful, otherwise false.
79
  /**
80
  * Builds a log entry text from timestamp, level and message.
81
  *
82
+ * @param int $timestamp Log timestamp.
83
  * @param string $level emergency|alert|critical|error|warning|notice|info|debug.
84
  * @param string $message Log message.
85
+ * @param array $context Additional information for log handlers.
86
  *
87
  * @return string Formatted log entry.
88
  */
275
  /**
276
  * Increment a log file suffix.
277
  *
278
+ * @param string $handle Log handle.
279
  * @param null|int $number Optional. Default null. Log suffix number to be incremented.
280
  *
281
  * @return bool True if increment was successful, otherwise false.
lite/includes/mailers/class-es-base-mailer.php CHANGED
@@ -15,7 +15,6 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
15
  *
16
  * @since 4.3.2
17
  * @var
18
- *
19
  */
20
  public $name;
21
 
@@ -24,7 +23,6 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
24
  *
25
  * @since 4.3.2
26
  * @var
27
- *
28
  */
29
  public $slug;
30
 
@@ -33,7 +31,6 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
33
  *
34
  * @since 4.3.2
35
  * @var string
36
- *
37
  */
38
  public $version = '1.0';
39
 
@@ -56,62 +53,61 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
56
  *
57
  * @since 4.2.0
58
  * @var array
59
- *
60
  */
61
  public $logger_context = array(
62
- 'source' => 'ig_es_email_sending'
63
  );
64
 
65
  /**
66
  * Flag to determine whether this mailer support batch sending or not
67
- *
68
  * @var boolean
69
- *
70
  * @since 4.7.0
71
  */
72
  public $support_batch_sending = false;
73
 
74
  /**
75
  * Stores batch sending mode
76
- *
77
  * @var boolean
78
- *
79
  * @since 4.7.1
80
  */
81
  public $batch_sending_mode = '';
82
 
83
  /**
84
  * Batch limit
85
- *
86
  * @var boolean
87
- *
88
  * @since 4.7.0
89
  */
90
  public $batch_limit = 0;
91
-
92
  /**
93
  * Current batch size
94
- *
95
  * @var boolean
96
- *
97
  * @since 4.7.0
98
  */
99
  public $current_batch_size = 0;
100
-
101
  /**
102
  * Batch data
103
- *
104
  * @var boolean
105
- *
106
  * @since 4.7.0
107
  */
108
  public $batch_data = array();
109
-
110
  /**
111
  * Links
112
- *
113
  * @var array
114
- *
115
  * @since 4.7.0
116
  */
117
  public $links = array();
@@ -176,7 +172,7 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
176
  *
177
  * @param string $name
178
  * @param string $value
179
- *
180
  * @since 4.6.14
181
  */
182
  public function set_header( $name, $value ) {
@@ -190,7 +186,7 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
190
  * Set email subject.
191
  *
192
  * @param string $subject
193
- *
194
  * @since 4.6.14
195
  */
196
  public function set_subject( $subject ) {
@@ -217,7 +213,7 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
217
  * Get the default params
218
  *
219
  * @return array
220
- *
221
  * @since 4.6.14
222
  */
223
  public function get_default_params() {
@@ -256,15 +252,15 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
256
 
257
  /**
258
  * Get placeholder variable name string
259
- *
260
  * @return string $variable_string
261
- *
262
  * @since 4.7.2
263
  */
264
  public function get_variable_string( $variable_name = '' ) {
265
  return $variable_name;
266
  }
267
-
268
  /**
269
  * Reset mailer data
270
  *
@@ -279,9 +275,9 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
279
 
280
  /**
281
  * Check if the batch limit has been reached or not
282
- *
283
  * @return boolean
284
- *
285
  * @since 4.7.0
286
  */
287
  public function is_batch_limit_reached() {
@@ -290,11 +286,11 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
290
 
291
  /**
292
  * Convert ES tags to mailer tags
293
- *
294
  * @param string $string
295
- *
296
  * @return string $string
297
- *
298
  * @since 4.7.0
299
  */
300
  public function convert_es_tags_to_mailer_tags( $string = '' ) {
@@ -303,18 +299,18 @@ if ( ! class_exists( 'ES_Base_Mailer' ) ) {
303
 
304
  /**
305
  * Send batch email
306
- *
307
  * @since 4.7.2
308
  */
309
  public function send_batch() {
310
-
311
  $response = $this->send_email();
312
  return $response;
313
  }
314
 
315
  /**
316
  * Clear mailer data
317
- *
318
  * @since 4.7.2
319
  */
320
  public function clear_email_data() {
15
  *
16
  * @since 4.3.2
17
  * @var
 
18
  */
19
  public $name;
20
 
23
  *
24
  * @since 4.3.2
25
  * @var
 
26
  */
27
  public $slug;
28
 
31
  *
32
  * @since 4.3.2
33
  * @var string
 
34
  */
35
  public $version = '1.0';
36
 
53
  *
54
  * @since 4.2.0
55
  * @var array
 
56
  */
57
  public $logger_context = array(
58
+ 'source' => 'ig_es_email_sending',
59
  );
60
 
61
  /**
62
  * Flag to determine whether this mailer support batch sending or not
63
+ *
64
  * @var boolean
65
+ *
66
  * @since 4.7.0
67
  */
68
  public $support_batch_sending = false;
69
 
70
  /**
71
  * Stores batch sending mode
72
+ *
73
  * @var boolean
74
+ *
75
  * @since 4.7.1
76
  */
77
  public $batch_sending_mode = '';
78
 
79
  /**
80
  * Batch limit
81
+ *
82
  * @var boolean
83
+ *
84
  * @since 4.7.0
85
  */
86
  public $batch_limit = 0;
87
+
88
  /**
89
  * Current batch size
90
+ *
91
  * @var boolean
92
+ *
93
  * @since 4.7.0
94
  */
95
  public $current_batch_size = 0;
96
+
97
  /**
98
  * Batch data
99
+ *
100
  * @var boolean
101
+ *
102
  * @since 4.7.0
103
  */
104
  public $batch_data = array();
105
+
106
  /**
107
  * Links
108
+ *
109
  * @var array
110
+ *
111
  * @since 4.7.0
112
  */
113
  public $links = array();
172
  *
173
  * @param string $name
174
  * @param string $value
175
+ *
176
  * @since 4.6.14
177
  */
178
  public function set_header( $name, $value ) {
186
  * Set email subject.
187
  *
188
  * @param string $subject
189
+ *
190
  * @since 4.6.14
191
  */
192
  public function set_subject( $subject ) {
213
  * Get the default params
214
  *
215
  * @return array
216
+ *
217
  * @since 4.6.14
218
  */
219
  public function get_default_params() {
252
 
253
  /**
254
  * Get placeholder variable name string
255
+ *
256
  * @return string $variable_string
257
+ *
258
  * @since 4.7.2
259
  */
260
  public function get_variable_string( $variable_name = '' ) {
261
  return $variable_name;
262
  }
263
+
264
  /**
265
  * Reset mailer data
266
  *
275
 
276
  /**
277
  * Check if the batch limit has been reached or not
278
+ *
279
  * @return boolean
280
+ *
281
  * @since 4.7.0
282
  */
283
  public function is_batch_limit_reached() {
286
 
287
  /**
288
  * Convert ES tags to mailer tags
289
+ *
290
  * @param string $string
291
+ *
292
  * @return string $string
293
+ *
294
  * @since 4.7.0
295
  */
296
  public function convert_es_tags_to_mailer_tags( $string = '' ) {
299
 
300
  /**
301
  * Send batch email
302
+ *
303
  * @since 4.7.2
304
  */
305
  public function send_batch() {
306
+
307
  $response = $this->send_email();
308
  return $response;
309
  }
310
 
311
  /**
312
  * Clear mailer data
313
+ *
314
  * @since 4.7.2
315
  */
316
  public function clear_email_data() {
lite/includes/mailers/class-es-pepipost-mailer.php CHANGED
@@ -15,7 +15,6 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
15
  *
16
  * @since 4.3.2
17
  * @var string
18
- *
19
  */
20
  public $api_url = 'https://api.pepipost.com/v2/sendEmail';
21
  /**
@@ -23,33 +22,32 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
23
  *
24
  * @since 4.3.2
25
  * @var string
26
- *
27
  */
28
  public $api_key = '';
29
 
30
  /**
31
  * Flag to determine whether this mailer support batch sending or not
32
- *
33
  * @var boolean
34
- *
35
  * @since 4.7.5
36
  */
37
  public $support_batch_sending = true;
38
 
39
  /**
40
  * Stores batch sending mode
41
- *
42
  * @var boolean
43
- *
44
  * @since 4.7.5
45
  */
46
  public $batch_sending_mode = 'multiple';
47
 
48
  /**
49
  * Batch limit
50
- *
51
  * @var boolean
52
- *
53
  * @since 4.7.5
54
  */
55
  public $batch_limit = 1000;
@@ -65,7 +63,7 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
65
 
66
  /**
67
  * Set mailer data
68
- *
69
  * @since 4.7.5
70
  */
71
  public function set_mailer_data() {
@@ -96,16 +94,16 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
96
  /**
97
  * Set email data
98
  * e.g. Sender email, name
99
- *
100
- * @since 4.7.5
101
  */
102
  public function set_email_data( $email_data = array() ) {
103
 
104
- $sender_email = ! empty( $email_data['sender_email'] ) ? $email_data['sender_email'] : '';
105
- $sender_name = ! empty( $email_data['sender_name'] ) ? $email_data['sender_name'] : '';
106
- $reply_to_email = ! empty( $email_data['reply_to_email'] ) ? $email_data['reply_to_email']: '';
107
- $subject = ! empty( $email_data['subject'] ) ? $email_data['subject'] : '';
108
- $content = ! empty( $email_data['content'] ) ? $email_data['content'] : '';
109
 
110
  $this->set_from( $sender_email, $sender_name );
111
  $this->set_reply_to( $reply_to_email );
@@ -115,14 +113,14 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
115
 
116
  /**
117
  * Add into batch
118
- *
119
  * @param string $email
120
- * @param array $merge_tags
121
- *
122
  * @since 4.7.5
123
  */
124
  public function add_into_batch( $email, $merge_tags = array() ) {
125
-
126
  $name = ig_es_get_data( $merge_tags, 'name', '' );
127
  $first_name = ig_es_get_data( $merge_tags, 'first_name', '' );
128
  $last_name = ig_es_get_data( $merge_tags, 'last_name', '' );
@@ -139,9 +137,9 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
139
  'contact_id' => $contact_id,
140
  'email' => $email,
141
  'guid' => $hash,
142
- 'list_ids' => $list_ids,
143
  );
144
-
145
  $subscribe_link = ES()->mailer->get_subscribe_link( $link_data );
146
  $unsubscribe_link = ES()->mailer->get_unsubscribe_link( $link_data );
147
  $link_variables = ES()->mailer->get_link_variable( $contact_id );
@@ -151,7 +149,7 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
151
  'NAME' => $name,
152
  'FIRSTNAME' => $first_name,
153
  'LASTNAME' => $last_name,
154
- 'LIST' => $list_name,
155
  'HASH' => $hash,
156
  'EMAIL' => $email,
157
  'contact_id' => $contact_id,
@@ -166,31 +164,31 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
166
  $recipient_variables = array_merge( $recipient_variables, $link_variables );
167
  }
168
 
169
- if ( ! empty( $tracking_pixel_url )) {
170
  $recipient_variables['tracking_pixel_url'] = $tracking_pixel_url;
171
  }
172
-
173
  $this->set_recipients(
174
  array(
175
- 'personalizations' => array(
176
  'recipient' => $email,
177
- 'attributes' => $recipient_variables
178
  ),
179
  )
180
  );
181
 
182
  $this->batch_data[] = $recipient_variables;
183
-
184
  $this->current_batch_size++;
185
  }
186
 
187
  /**
188
  * Convert ES tags to mailer tags
189
- *
190
  * @param string $string
191
- *
192
  * @return string $string
193
- *
194
  * @since 4.7.5
195
  */
196
  public function convert_es_tags_to_mailer_tags( $string = '' ) {
@@ -205,10 +203,10 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
205
 
206
  /**
207
  * Get variable prefix
208
- *
209
  * @return string
210
- *
211
- * @since 4.7.5
212
  */
213
  public function get_variable_prefix() {
214
  return '[%';
@@ -216,10 +214,10 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
216
 
217
  /**
218
  * Get variable suffix
219
- *
220
  * @return string
221
- *
222
- * @since 4.7.5
223
  */
224
  public function get_variable_suffix() {
225
  return '%]';
@@ -231,7 +229,7 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
231
  * Pepipost requires a JSON, so we encode the body.
232
  *
233
  * @return string json encoded body data
234
- *
235
  * @since 4.7.5
236
  */
237
  public function get_body() {
@@ -244,7 +242,7 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
244
  * Set email subject.
245
  *
246
  * @param string $subject
247
- *
248
  * @since 4.7.5
249
  */
250
  public function set_subject( $subject ) {
@@ -258,9 +256,9 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
258
 
259
  /**
260
  * Set email content
261
- *
262
  * @param string content
263
- *
264
  * @since 4.7.5
265
  */
266
  public function set_content( $content ) {
@@ -278,10 +276,10 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
278
 
279
  /**
280
  * Set from
281
- *
282
  * @param string $email
283
  * @param string $name
284
- *
285
  * @since 4.7.5
286
  */
287
  public function set_from( $email, $name = '' ) {
@@ -295,16 +293,16 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
295
  array(
296
  'from' => array(
297
  'fromEmail' => $email,
298
- 'fromName' => $name
299
- )
300
  )
301
  );
302
  } else {
303
  $this->set_body_param(
304
  array(
305
  'from' => array(
306
- 'fromEmail' => $email
307
- )
308
  )
309
  );
310
  }
@@ -312,9 +310,9 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
312
 
313
  /**
314
  * Set reply to
315
- *
316
  * @param string $email
317
- *
318
  * @since 4.7.5
319
  */
320
  public function set_reply_to( $email ) {
@@ -332,9 +330,9 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
332
 
333
  /**
334
  * Set recipients
335
- *
336
  * @param array $recipients
337
- *
338
  * @since 4.7.5
339
  */
340
  public function set_recipients( $recipients ) {
@@ -356,7 +354,7 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
356
 
357
  $this->set_body_param(
358
  array(
359
- $kind => array( $recipient_data )
360
  )
361
  );
362
  }
@@ -366,7 +364,7 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
366
  * Pepipost accepts an array of files content in body, so we will include all files and send.
367
  *
368
  * @param array $attachments
369
- *
370
  * @since 4.7.5
371
  */
372
  public function set_attachments( $attachments ) {
@@ -395,7 +393,7 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
395
  $filetype = mime_content_type( $attachment_path );
396
 
397
  $data[] = array(
398
- 'fileName' => empty( $attachment_name ) ? 'file-' . wp_hash( microtime() ) . '.' . $filetype: trim( $attachment_name ), // required string, no CRLF.
399
  'fileContent' => base64_encode( $file ), // string, 1 character.
400
  );
401
  }
@@ -403,7 +401,7 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
403
  if ( ! empty( $data ) ) {
404
  $this->set_body_param(
405
  array(
406
- 'attachments' => $data
407
  )
408
  );
409
  }
@@ -411,26 +409,26 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
411
 
412
  /**
413
  * Set open/click tracking options
414
- *
415
  * @since 4.7.5
416
  */
417
  public function set_tracking_options() {
418
 
419
  $tracking_settings = array(
420
  'opentrack' => ES()->mailer->can_track_open() ? 1 : 0,
421
- 'clicktrack' => ES()->mailer->can_track_clicks() ? 1: 0,
422
  );
423
 
424
  $this->set_body_param(
425
  array(
426
- 'settings' => $tracking_settings
427
  )
428
  );
429
  }
430
 
431
  /**
432
  * Clear batch
433
- *
434
  * @since 4.7.5
435
  */
436
  public function clear_batch() {
@@ -465,12 +463,12 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
465
  $this->set_content( $message->body );
466
  $this->set_recipients(
467
  array(
468
- 'personalizations' => array(
469
  'recipient' => $message->to,
470
- )
471
  )
472
  );
473
-
474
  if ( $message->attachments ) {
475
  $this->set_attachments( $message->attachments );
476
  }
@@ -482,17 +480,20 @@ if ( ! class_exists( 'ES_Pepipost_Mailer' ) ) {
482
 
483
  /**
484
  * Send email using Pepipost API
485
- *
486
  * @since 4.7.5
487
  */
488
  public function send_email() {
489
 
490
  ES()->logger->info( 'Start Sending Email Using Pepipost', $this->logger_context );
491
 
492
- $params = array_merge_recursive( $this->get_default_params(), array(
493
- 'headers' => $this->get_headers(),
494
- 'body' => $this->get_body(),
495
- ));
 
 
 
496
 
497
  $response = wp_remote_post( $this->api_url, $params );
498
  if ( ! is_wp_error( $response ) ) {
15
  *
16
  * @since 4.3.2
17
  * @var string
 
18
  */
19
  public $api_url = 'https://api.pepipost.com/v2/sendEmail';
20
  /**
22
  *
23
  * @since 4.3.2
24
  * @var string
 
25
  */
26
  public $api_key = '';
27
 
28
  /**
29
  * Flag to determine whether this mailer support batch sending or not
30
+ *
31
  * @var boolean
32
+ *
33
  * @since 4.7.5
34
  */
35
  public $support_batch_sending = true;
36
 
37
  /**
38
  * Stores batch sending mode
39
+ *
40
  * @var boolean
41
+ *
42
  * @since 4.7.5
43
  */
44
  public $batch_sending_mode = 'multiple';
45
 
46
  /**
47
  * Batch limit
48
+ *
49
  * @var boolean
50
+ *
51
  * @since 4.7.5
52
  */
53
  public $batch_limit = 1000;
63
 
64
  /**
65
  * Set mailer data
66
+ *
67
  * @since 4.7.5
68
  */
69
  public function set_mailer_data() {
94
  /**
95
  * Set email data
96
  * e.g. Sender email, name
97
+ *
98
+ * @since 4.7.5
99
  */
100
  public function set_email_data( $email_data = array() ) {
101
 
102
+ $sender_email = ! empty( $email_data['sender_email'] ) ? $email_data['sender_email'] : '';
103
+ $sender_name = ! empty( $email_data['sender_name'] ) ? $email_data['sender_name'] : '';
104
+ $reply_to_email = ! empty( $email_data['reply_to_email'] ) ? $email_data['reply_to_email'] : '';
105
+ $subject = ! empty( $email_data['subject'] ) ? $email_data['subject'] : '';
106
+ $content = ! empty( $email_data['content'] ) ? $email_data['content'] : '';
107
 
108
  $this->set_from( $sender_email, $sender_name );
109
  $this->set_reply_to( $reply_to_email );
113
 
114
  /**
115
  * Add into batch
116
+ *
117
  * @param string $email
118
+ * @param array $merge_tags
119
+ *
120
  * @since 4.7.5
121
  */
122
  public function add_into_batch( $email, $merge_tags = array() ) {
123
+
124
  $name = ig_es_get_data( $merge_tags, 'name', '' );
125
  $first_name = ig_es_get_data( $merge_tags, 'first_name', '' );
126
  $last_name = ig_es_get_data( $merge_tags, 'last_name', '' );
137
  'contact_id' => $contact_id,
138
  'email' => $email,
139
  'guid' => $hash,
140
+ 'list_ids' => $list_ids,
141
  );
142
+
143
  $subscribe_link = ES()->mailer->get_subscribe_link( $link_data );
144
  $unsubscribe_link = ES()->mailer->get_unsubscribe_link( $link_data );
145
  $link_variables = ES()->mailer->get_link_variable( $contact_id );
149
  'NAME' => $name,
150
  'FIRSTNAME' => $first_name,
151
  'LASTNAME' => $last_name,
152
+ 'LIST' => $list_name,
153
  'HASH' => $hash,
154
  'EMAIL' => $email,
155
  'contact_id' => $contact_id,
164
  $recipient_variables = array_merge( $recipient_variables, $link_variables );
165
  }
166
 
167
+ if ( ! empty( $tracking_pixel_url ) ) {
168
  $recipient_variables['tracking_pixel_url'] = $tracking_pixel_url;
169
  }
170
+
171
  $this->set_recipients(
172
  array(
173
+ 'personalizations' => array(
174
  'recipient' => $email,
175
+ 'attributes' => $recipient_variables,
176
  ),
177
  )
178
  );
179
 
180
  $this->batch_data[] = $recipient_variables;
181
+
182
  $this->current_batch_size++;
183
  }
184
 
185
  /**
186
  * Convert ES tags to mailer tags
187
+ *
188
  * @param string $string
189
+ *
190
  * @return string $string
191
+ *
192
  * @since 4.7.5
193
  */
194
  public function convert_es_tags_to_mailer_tags( $string = '' ) {
203
 
204
  /**
205
  * Get variable prefix
206
+ *
207
  * @return string
208
+ *
209
+ * @since 4.7.5
210
  */
211
  public function get_variable_prefix() {
212
  return '[%';
214
 
215
  /**
216
  * Get variable suffix
217
+ *
218
  * @return string
219
+ *
220
+ * @since 4.7.5
221
  */
222
  public function get_variable_suffix() {
223
  return '%]';
229
  * Pepipost requires a JSON, so we encode the body.
230
  *
231
  * @return string json encoded body data
232
+ *
233
  * @since 4.7.5
234
  */
235
  public function get_body() {
242
  * Set email subject.
243
  *
244
  * @param string $subject
245
+ *
246
  * @since 4.7.5
247
  */
248
  public function set_subject( $subject ) {
256
 
257
  /**
258
  * Set email content
259
+ *
260
  * @param string content
261
+ *
262
  * @since 4.7.5
263
  */
264
  public function set_content( $content ) {
276
 
277
  /**
278
  * Set from
279
+ *
280
  * @param string $email
281
  * @param string $name
282
+ *
283
  * @since 4.7.5
284
  */
285
  public function set_from( $email, $name = '' ) {
293
  array(
294
  'from' => array(
295
  'fromEmail' => $email,
296
+ 'fromName' => $name,
297
+ ),
298
  )
299
  );
300
  } else {
301
  $this->set_body_param(
302
  array(
303
  'from' => array(
304
+ 'fromEmail' => $email,
305
+ ),
306
  )
307
  );
308
  }
310
 
311
  /**
312
  * Set reply to
313
+ *
314
  * @param string $email
315
+ *
316
  * @since 4.7.5
317
  */
318
  public function set_reply_to( $email ) {
330
 
331
  /**
332
  * Set recipients
333
+ *
334
  * @param array $recipients
335
+ *
336
  * @since 4.7.5
337
  */
338
  public function set_recipients( $recipients ) {
354
 
355
  $this->set_body_param(
356
  array(
357
+ $kind => array( $recipient_data ),
358
  )
359
  );
360
  }
364
  * Pepipost accepts an array of files content in body, so we will include all files and send.
365
  *
366
  * @param array $attachments
367
+ *
368
  * @since 4.7.5
369
  */
370
  public function set_attachments( $attachments ) {
393
  $filetype = mime_content_type( $attachment_path );
394
 
395
  $data[] = array(
396
+ 'fileName' => empty( $attachment_name ) ? 'file-' . wp_hash( microtime() ) . '.' . $filetype : trim( $attachment_name ), // required string, no CRLF.
397
  'fileContent' => base64_encode( $file ), // string, 1 character.
398
  );
399
  }
401
  if ( ! empty( $data ) ) {
402
  $this->set_body_param(
403
  array(
404
+ 'attachments' => $data,
405
  )
406
  );
407
  }
409
 
410
  /**
411
  * Set open/click tracking options
412
+ *
413
  * @since 4.7.5
414
  */
415
  public function set_tracking_options() {
416
 
417
  $tracking_settings = array(
418
  'opentrack' => ES()->mailer->can_track_open() ? 1 : 0,
419
+ 'clicktrack' => ES()->mailer->can_track_clicks() ? 1 : 0,
420
  );
421
 
422
  $this->set_body_param(
423
  array(
424
+ 'settings' => $tracking_settings,
425
  )
426
  );
427
  }
428
 
429
  /**
430
  * Clear batch
431
+ *
432
  * @since 4.7.5
433
  */
434
  public function clear_batch() {
463
  $this->set_content( $message->body );
464
  $this->set_recipients(
465
  array(
466
+ 'personalizations' => array(
467
  'recipient' => $message->to,
468
+ ),
469
  )
470
  );
471
+
472
  if ( $message->attachments ) {
473
  $this->set_attachments( $message->attachments );
474
  }
480
 
481
  /**
482
  * Send email using Pepipost API
483
+ *
484
  * @since 4.7.5
485
  */
486
  public function send_email() {
487
 
488
  ES()->logger->info( 'Start Sending Email Using Pepipost', $this->logger_context );
489
 
490
+ $params = array_merge_recursive(
491
+ $this->get_default_params(),
492
+ array(
493
+ 'headers' => $this->get_headers(),
494
+ 'body' => $this->get_body(),
495
+ )
496
+ );
497
 
498
  $response = wp_remote_post( $this->api_url, $params );
499
  if ( ! is_wp_error( $response ) ) {
lite/includes/mailers/class-es-phpmail-mailer.php CHANGED
@@ -31,14 +31,14 @@ if ( ! class_exists( 'ES_Phpmail_Mailer' ) ) {
31
 
32
  global $wp_version;
33
 
34
- ES()->logger->info( 'Start Sending Email Using PHP Mail', $this->logger_context );
35
 
36
  if ( version_compare( $wp_version, '5.5', '<' ) ) {
37
  require_once ABSPATH . WPINC . '/class-phpmailer.php';
38
  } else {
39
  require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
40
  require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
41
-
42
  // Check if PHPMailer class already exists before creating an alias for it.
43
  if ( ! class_exists( 'PHPMailer' ) ) {
44
  class_alias( PHPMailer\PHPMailer\PHPMailer::class, 'PHPMailer' );
@@ -49,11 +49,11 @@ if ( ! class_exists( 'ES_Phpmail_Mailer' ) ) {
49
  class_alias( PHPMailer\PHPMailer\Exception::class, 'phpmailerException' );
50
  }
51
  }
52
-
53
- $phpmailer = new PHPMailer( true );
54
- $phpmailer->From = $message->from;
55
- $phpmailer->FromName = $message->from_name;
56
- $phpmailer->CharSet = $message->charset;
57
  $phpmailer->ClearAllRecipients();
58
  $phpmailer->clearAttachments();
59
  $phpmailer->clearCustomHeaders();
@@ -70,10 +70,10 @@ if ( ! class_exists( 'ES_Phpmail_Mailer' ) ) {
70
  $phpmailer->addCustomHeader( 'List-Unsubscribe', $list_unsubscribe_header );
71
  $phpmailer->addCustomHeader( 'List-Unsubscribe-Post', 'List-Unsubscribe=One-Click' );
72
  }
73
-
74
  $phpmailer->Subject = $message->subject;
75
  $phpmailer->Body = $message->body;
76
- $phpmailer->AltBody = $message->body_text; //Text Email Body for non html email client
77
 
78
  if ( ! empty( $message->attachments ) ) {
79
  $attachments = $message->attachments;
@@ -85,7 +85,7 @@ if ( ! class_exists( 'ES_Phpmail_Mailer' ) ) {
85
  }
86
  }
87
  }
88
-
89
  try {
90
  if ( ! $phpmailer->send() ) {
91
  ES()->logger->error( '[Error in Email Sending] : ' . $message->to . ' Error: ' . $phpmailer->ErrorInfo, $this->logger_context );
31
 
32
  global $wp_version;
33
 
34
+ ES()->logger->info( 'Start Sending Email Using PHP Mail', $this->logger_context );
35
 
36
  if ( version_compare( $wp_version, '5.5', '<' ) ) {
37
  require_once ABSPATH . WPINC . '/class-phpmailer.php';
38
  } else {
39
  require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
40
  require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
41
+
42
  // Check if PHPMailer class already exists before creating an alias for it.
43
  if ( ! class_exists( 'PHPMailer' ) ) {
44
  class_alias( PHPMailer\PHPMailer\PHPMailer::class, 'PHPMailer' );
49
  class_alias( PHPMailer\PHPMailer\Exception::class, 'phpmailerException' );
50
  }
51
  }
52
+
53
+ $phpmailer = new PHPMailer( true );
54
+ $phpmailer->From = $message->from;
55
+ $phpmailer->FromName = $message->from_name;
56
+ $phpmailer->CharSet = $message->charset;
57
  $phpmailer->ClearAllRecipients();
58
  $phpmailer->clearAttachments();
59
  $phpmailer->clearCustomHeaders();
70
  $phpmailer->addCustomHeader( 'List-Unsubscribe', $list_unsubscribe_header );
71
  $phpmailer->addCustomHeader( 'List-Unsubscribe-Post', 'List-Unsubscribe=One-Click' );
72
  }
73
+
74
  $phpmailer->Subject = $message->subject;
75
  $phpmailer->Body = $message->body;
76
+ $phpmailer->AltBody = $message->body_text; // Text Email Body for non html email client
77
 
78
  if ( ! empty( $message->attachments ) ) {
79
  $attachments = $message->attachments;
85
  }
86
  }
87
  }
88
+
89
  try {
90
  if ( ! $phpmailer->send() ) {
91
  ES()->logger->error( '[Error in Email Sending] : ' . $message->to . ' Error: ' . $phpmailer->ErrorInfo, $this->logger_context );
lite/includes/notices/class-es-admin-notices.php CHANGED
@@ -20,7 +20,7 @@ class ES_Admin_Notices {
20
  * @var array
21
  */
22
  private static $core_notices = array(
23
- 'update' => 'update_notice',
24
  'trial_consent' => 'show_trial_consent_notice',
25
  );
26
 
@@ -156,7 +156,7 @@ class ES_Admin_Notices {
156
  $ig_current_date = strtotime( date_i18n( $timezone_format ) );
157
 
158
  if ( ! empty( $notice_args['include'] ) && file_exists( $notice_args['include'] ) ) {
159
- include_once $notice_args['include'] ;
160
  }
161
 
162
  if ( ! empty( $notice_args['html'] ) ) {
@@ -164,7 +164,7 @@ class ES_Admin_Notices {
164
  }
165
 
166
  // if ( $notice_html ) {
167
- // include dirname( __FILE__ ) . '/views/html-notice-custom.php';
168
  // }
169
  }
170
  }
@@ -175,16 +175,16 @@ class ES_Admin_Notices {
175
  * If we need to update, include a message with the update button.
176
  */
177
  public static function update_notice() {
178
-
179
  $latest_version_to_update = ES_Install::get_latest_db_version_to_update();
180
-
181
  if ( version_compare( get_ig_es_db_version(), $latest_version_to_update, '<' ) ) {
182
  // Database is updating now.
183
  include dirname( __FILE__ ) . '/views/html-notice-updating.php';
184
-
185
  // Show button to to "Run the updater"
186
- //include dirname( __FILE__ ) . '/views/html-notice-update.php';
187
-
188
  } else {
189
  include dirname( __FILE__ ) . '/views/html-notice-updated.php';
190
  }
@@ -192,9 +192,9 @@ class ES_Admin_Notices {
192
 
193
  /**
194
  * Show trial optin notice.
195
- *
196
  * @since 4.6.1
197
- *
198
  * @modified 4.6.2 Added not is_premium condition to disable notice when the user activates premium plugin after using the lite version.
199
  */
200
  public static function show_trial_consent_notice() {
@@ -242,14 +242,14 @@ class ES_Admin_Notices {
242
  header( "Location: {$url}" );
243
  exit();
244
  } else {
245
-
246
  // Remove wp cron notice if user have acknowledged it.
247
  if ( 'wp_cron_notice' === $option_name ) {
248
  self::remove_notice( 'show_wp_cron' );
249
- } else if ( 'trial_consent' === $option_name ) {
250
  self::remove_notice( $option_name );
251
  }
252
-
253
  $referer = wp_get_referer();
254
  wp_safe_redirect( $referer );
255
  }
20
  * @var array
21
  */
22
  private static $core_notices = array(
23
+ 'update' => 'update_notice',
24
  'trial_consent' => 'show_trial_consent_notice',
25
  );
26
 
156
  $ig_current_date = strtotime( date_i18n( $timezone_format ) );
157
 
158
  if ( ! empty( $notice_args['include'] ) && file_exists( $notice_args['include'] ) ) {
159
+ include_once $notice_args['include'];
160
  }
161
 
162
  if ( ! empty( $notice_args['html'] ) ) {
164
  }
165
 
166
  // if ( $notice_html ) {
167
+ // include dirname( __FILE__ ) . '/views/html-notice-custom.php';
168
  // }
169
  }
170
  }
175
  * If we need to update, include a message with the update button.
176
  */
177
  public static function update_notice() {
178
+
179
  $latest_version_to_update = ES_Install::get_latest_db_version_to_update();
180
+
181
  if ( version_compare( get_ig_es_db_version(), $latest_version_to_update, '<' ) ) {
182
  // Database is updating now.
183
  include dirname( __FILE__ ) . '/views/html-notice-updating.php';
184
+
185
  // Show button to to "Run the updater"
186
+ // include dirname( __FILE__ ) . '/views/html-notice-update.php';
187
+
188
  } else {
189
  include dirname( __FILE__ ) . '/views/html-notice-updated.php';
190
  }
192
 
193
  /**
194
  * Show trial optin notice.
195
+ *
196
  * @since 4.6.1
197
+ *
198
  * @modified 4.6.2 Added not is_premium condition to disable notice when the user activates premium plugin after using the lite version.
199
  */
200
  public static function show_trial_consent_notice() {
242
  header( "Location: {$url}" );
243
  exit();
244
  } else {
245
+
246
  // Remove wp cron notice if user have acknowledged it.
247
  if ( 'wp_cron_notice' === $option_name ) {
248
  self::remove_notice( 'show_wp_cron' );
249
+ } elseif ( 'trial_consent' === $option_name ) {
250
  self::remove_notice( $option_name );
251
  }
252
+
253
  $referer = wp_get_referer();
254
  wp_safe_redirect( $referer );
255
  }
lite/includes/notices/views/ig-es-bfcm-offer.php CHANGED
@@ -9,10 +9,10 @@
9
  </style>
10
  <?php
11
 
12
- if ( ( get_option( 'ig_es_offer_bfcm_2020' ) !== 'yes' ) && ( $ig_current_date >= strtotime( '2020-11-24' ) ) && ( $ig_current_date <= strtotime( '2020-12-02' ) )) { ?>
13
  <div class="wrap">
14
  <div class="ig_es_offer">
15
- <a target="_blank" href="?es_dismiss_admin_notice=1&option_name=offer_bfcm_2020"><img style="margin:0 auto" src="<?php echo esc_url ( ES_PLUGIN_URL ); ?>lite/admin/images/bfcm_2020.jpg"/></a>
16
  </div>
17
  </div>
18
 
9
  </style>
10
  <?php
11
 
12
+ if ( ( get_option( 'ig_es_offer_bfcm_2020' ) !== 'yes' ) && ( $ig_current_date >= strtotime( '2020-11-24' ) ) && ( $ig_current_date <= strtotime( '2020-12-02' ) ) ) { ?>
13
  <div class="wrap">
14
  <div class="ig_es_offer">
15
+ <a target="_blank" href="?es_dismiss_admin_notice=1&option_name=offer_bfcm_2020"><img style="margin:0 auto" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/bfcm_2020.jpg"/></a>
16
  </div>
17
  </div>
18
 
lite/includes/notices/views/ig-es-offer.php CHANGED
@@ -9,9 +9,9 @@
9
  </style>
10
  <?php
11
 
12
- if ( ( get_option( 'ig_es_offer_covid_19' ) !== 'yes' ) && ( $ig_current_date >= strtotime( '2020-04-08' ) ) && ( $ig_current_date <= strtotime( '2020-04-30' ) )) { ?>
13
  <div class="ig_es_offer">
14
- <a target="_blank" href="?es_dismiss_admin_notice=1&option_name=offer_covid_19"><img src="<?php echo esc_url ( ES_PLUGIN_URL ); ?>/lite/admin/images/covid-19.png"/></a>
15
  </div>
16
 
17
  <?php } ?>
9
  </style>
10
  <?php
11
 
12
+ if ( ( get_option( 'ig_es_offer_covid_19' ) !== 'yes' ) && ( $ig_current_date >= strtotime( '2020-04-08' ) ) && ( $ig_current_date <= strtotime( '2020-04-30' ) ) ) { ?>
13
  <div class="ig_es_offer">
14
+ <a target="_blank" href="?es_dismiss_admin_notice=1&option_name=offer_covid_19"><img src="<?php echo esc_url( ES_PLUGIN_URL ); ?>/lite/admin/images/covid-19.png"/></a>
15
  </div>
16
 
17
  <?php } ?>
lite/includes/notices/views/trial-consent.php CHANGED
@@ -7,18 +7,18 @@ if ( ! defined( 'ABSPATH' ) ) {
7
  exit;
8
  }
9
 
10
- $referer = wp_get_referer();
11
  $optin_url = wp_nonce_url(
12
  add_query_arg( 'ig_es_trial_consent', 'yes', $referer ),
13
  'ig_es_trial_consent'
14
  );
15
 
16
  $optout_url = wp_nonce_url(
17
- add_query_arg(
18
  array(
19
  'es_dismiss_admin_notice' => 1,
20
  'option_name' => 'trial_consent',
21
- ),
22
  $referer
23
  ),
24
  'ig_es_trial_consent'
7
  exit;
8
  }
9
 
10
+ $referer = wp_get_referer();
11
  $optin_url = wp_nonce_url(
12
  add_query_arg( 'ig_es_trial_consent', 'yes', $referer ),
13
  'ig_es_trial_consent'
14
  );
15
 
16
  $optout_url = wp_nonce_url(
17
+ add_query_arg(
18
  array(
19
  'es_dismiss_admin_notice' => 1,
20
  'option_name' => 'trial_consent',
21
+ ),
22
  $referer
23
  ),
24
  'ig_es_trial_consent'
lite/includes/notices/views/trial-to-premium-offer.php CHANGED
@@ -12,12 +12,12 @@ $referer = wp_get_referer();
12
  $notice_optin_action = 'ig_es_trial_to_premium_redirect';
13
 
14
  $optin_url = wp_nonce_url(
15
- add_query_arg(
16
  array(
17
  'es_dismiss_admin_notice' => 1,
18
  'option_name' => 'trial_to_premium_notice',
19
  'action' => $notice_optin_action,
20
- ),
21
  $referer
22
  ),
23
  $notice_optin_action
@@ -26,12 +26,12 @@ $optin_url = wp_nonce_url(
26
  $notice_optout_action = 'ig_es_trial_to_premium_dismiss';
27
 
28
  $optout_url = wp_nonce_url(
29
- add_query_arg(
30
  array(
31
  'es_dismiss_admin_notice' => 1,
32
  'option_name' => 'trial_to_premium_notice',
33
  'action' => $notice_optout_action,
34
- ),
35
  $referer
36
  ),
37
  $notice_optout_action
@@ -44,7 +44,7 @@ $discount_messages = array(
44
  'halloween' => array(
45
  'message' => __( 'Get flat <strong>20%</strong> discount on annual plan and <strong>35%</strong> discount on lifetime plan if you upgrade now!<br/><strong>No coupon code</strong> required. Discount will be applied automatically.', 'email-subscribers' ),
46
  ),
47
- 'bfcm' => array(
48
  'message' => __( 'Get flat <strong>20%</strong> discount on annual plan and <strong>35%</strong> discount on lifetime plan if you upgrade now!<br/><strong>No coupon code</strong> required. Discount will be applied automatically.', 'email-subscribers' ),
49
  ),
50
  );
@@ -56,7 +56,7 @@ $offers_date_ranges = array(
56
  'start_date' => '2020-10-30',
57
  'end_date' => '2020-11-02',
58
  ),
59
- 'bfcm' => array(
60
  'start_date' => '2020-11-25',
61
  'end_date' => '2020-12-02',
62
  ),
@@ -65,9 +65,9 @@ $offers_date_ranges = array(
65
  foreach ( $offers_date_ranges as $offer_type => $offer_dates ) {
66
  $offer_start_date = $offer_dates['start_date'];
67
  $offer_end_date = $offer_dates['end_date'];
68
-
69
  if ( ( $ig_current_date >= strtotime( $offer_start_date ) ) && ( $ig_current_date <= strtotime( $offer_end_date ) ) ) {
70
- $offer_type_to_show = $offer_type;
71
  break;
72
  }
73
  }
@@ -75,7 +75,7 @@ foreach ( $offers_date_ranges as $offer_type => $offer_dates ) {
75
  $trial_expiration_message = '';
76
  if ( $remaining_trial_days > 1 ) {
77
  /* translators: 1. Remaining trial days. 2. day or days text based on number of remaining trial days. */
78
- $trial_expiration_message = sprintf( __( 'Your free trial is going to <strong>expire in %1$s %2$s</strong>.', 'email-subscribers' ), $remaining_trial_days, $day_or_days);
79
  } else {
80
  $trial_expiration_message = __( 'Today is the <strong>last day</strong> of your free trial.', 'email-subscribers' );
81
  }
12
  $notice_optin_action = 'ig_es_trial_to_premium_redirect';
13
 
14
  $optin_url = wp_nonce_url(
15
+ add_query_arg(
16
  array(
17
  'es_dismiss_admin_notice' => 1,
18
  'option_name' => 'trial_to_premium_notice',
19
  'action' => $notice_optin_action,
20
+ ),
21
  $referer
22
  ),
23
  $notice_optin_action
26
  $notice_optout_action = 'ig_es_trial_to_premium_dismiss';
27
 
28
  $optout_url = wp_nonce_url(
29
+ add_query_arg(
30
  array(
31
  'es_dismiss_admin_notice' => 1,
32
  'option_name' => 'trial_to_premium_notice',
33
  'action' => $notice_optout_action,
34
+ ),
35
  $referer
36
  ),
37
  $notice_optout_action
44
  'halloween' => array(
45
  'message' => __( 'Get flat <strong>20%</strong> discount on annual plan and <strong>35%</strong> discount on lifetime plan if you upgrade now!<br/><strong>No coupon code</strong> required. Discount will be applied automatically.', 'email-subscribers' ),
46
  ),
47
+ 'bfcm' => array(
48
  'message' => __( 'Get flat <strong>20%</strong> discount on annual plan and <strong>35%</strong> discount on lifetime plan if you upgrade now!<br/><strong>No coupon code</strong> required. Discount will be applied automatically.', 'email-subscribers' ),
49
  ),
50
  );
56
  'start_date' => '2020-10-30',
57
  'end_date' => '2020-11-02',
58
  ),
59
+ 'bfcm' => array(
60
  'start_date' => '2020-11-25',
61
  'end_date' => '2020-12-02',
62
  ),
65
  foreach ( $offers_date_ranges as $offer_type => $offer_dates ) {
66
  $offer_start_date = $offer_dates['start_date'];
67
  $offer_end_date = $offer_dates['end_date'];
68
+
69
  if ( ( $ig_current_date >= strtotime( $offer_start_date ) ) && ( $ig_current_date <= strtotime( $offer_end_date ) ) ) {
70
+ $offer_type_to_show = $offer_type;
71
  break;
72
  }
73
  }
75
  $trial_expiration_message = '';
76
  if ( $remaining_trial_days > 1 ) {
77
  /* translators: 1. Remaining trial days. 2. day or days text based on number of remaining trial days. */
78
+ $trial_expiration_message = sprintf( __( 'Your free trial is going to <strong>expire in %1$s %2$s</strong>.', 'email-subscribers' ), $remaining_trial_days, $day_or_days );
79
  } else {
80
  $trial_expiration_message = __( 'Today is the <strong>last day</strong> of your free trial.', 'email-subscribers' );
81
  }
lite/includes/premium-services-ui/class-ig-es-premium-services-ui.php CHANGED
@@ -14,10 +14,9 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  */
15
 
16
  if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
17
-
18
  /**
19
  * The premium services-ui specific functionality of the plugin.
20
- *
21
  */
22
  class IG_ES_Premium_Services_UI {
23
 
@@ -27,7 +26,7 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
27
  * @var Onboarding instance
28
  */
29
  protected static $instance = null;
30
-
31
  /**
32
  * Initialize the class and set its properties.
33
  *
@@ -36,10 +35,10 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
36
  public function __construct() {
37
  add_action( 'init', array( $this, 'init' ) );
38
  }
39
-
40
  /**
41
  * Get class instance.
42
- *
43
  * @since 4.6.1
44
  */
45
  public static function instance() {
@@ -50,14 +49,14 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
50
  }
51
  /**
52
  * Method to hook required action/filters to show ui components used in premium services.
53
- *
54
  * @since 4.6.1
55
  */
56
  public function init() {
57
 
58
  // Add ui components only if trial is valid or user is a premium user.
59
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
60
-
61
  // Add UI for CSS inliner only if service is valid.
62
  if ( ES()->validate_service_request( array( 'css_inliner' ) ) ) {
63
  add_action( 'ig_es_after_broadcast_left_pan_settings', array( &$this, 'add_custom_css_field' ) );
@@ -96,7 +95,7 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
96
  </div>
97
  <?php
98
  }
99
-
100
  /**
101
  * Add Custom CSS block for ES Template
102
  *
@@ -118,7 +117,7 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
118
  </p>
119
  <?php
120
  }
121
-
122
  /**
123
  * Hooked to save_post WordPress action
124
  * Update ES Template data
@@ -147,7 +146,7 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
147
  if ( 'es_template' != $post->post_type ) {
148
  return;
149
  }
150
-
151
  if ( ! empty( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'update-post_' . $post_id ) ) {
152
  // Get custom CSS code. Don't sanitize it since it removes CSS code.
153
  $es_custom_css = ig_es_get_data( $_POST, 'es_custom_css', false, false );
@@ -163,19 +162,19 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
163
  do_action( 'ig_es_save_template', $post_id, $post_id );
164
  }
165
  }
166
-
167
  /**
168
  * Method to add metaboxes
169
- *
170
  * @since 4.6.1
171
  */
172
  public function add_metaboxes() {
173
  add_meta_box( 'es_spam', __( 'Get Spam Score', 'email-subscribers' ), array( &$this, 'add_spam_score_metabox' ), 'es_template', 'side', 'default' );
174
  }
175
-
176
  /**
177
  * Method to add spam score metabox
178
- *
179
  * @since 4.6.1
180
  */
181
  public function add_spam_score_metabox() {
@@ -193,14 +192,13 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
193
  </div>
194
  <?php
195
  }
196
-
197
  /**
198
  * Method to show left pan fields in broadcast summary section.
199
  *
200
  * @param array $broadcast_data Broadcast data
201
  *
202
  * @since 4.4.7
203
- *
204
  */
205
  public function add_check_spam_score_button( $broadcast_data = array() ) {
206
  ?>
@@ -208,9 +206,11 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
208
  <span class="pt-3 text-sm font-medium leading-5 text-gray-700"><?php echo esc_html__( 'Get Spam Score', 'email-subscribers' ); ?> </span>
209
  <button type="button" id="spam_score"
210
  class="float-right es_spam rounded-md border text-indigo-600 border-indigo-500 text-sm leading-5 font-medium transition ease-in-out duration-150 select-none inline-flex justify-center hover:text-indigo-500 hover:border-indigo-600 hover:shadow-md focus:outline-none focus:shadow-outline-indigo focus:shadow-lg px-3 py-1">
211
- <?php
212
- echo esc_html__( 'Check',
213
- 'email-subscribers' );
 
 
214
  ?>
215
  </button>
216
  <img src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/spinner-2x.gif" class="es-loader-img inline-flex align-middle pl-2 h-5 w-7" style="display:none;"/>
@@ -251,7 +251,7 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
251
  * @return void
252
  */
253
  public function add_broadcast_utm_tracking_option( $broadcast_data = array() ) {
254
- $enable_utm_tracking = ! empty( $broadcast_data['meta']['enable_utm_tracking'] ) ? $broadcast_data['meta']['enable_utm_tracking'] : get_option( 'ig_es_track_utm', 'no' );
255
 
256
  $campaign_name = ! empty( $broadcast_data['meta']['es_utm_campaign'] ) ? $broadcast_data['meta']['es_utm_campaign'] : '';
257
 
@@ -280,24 +280,24 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
280
 
281
  /**
282
  * Method to register UTM tracking side metabox on ES template page
283
- *
284
  * @since 4.6.2
285
  */
286
  public function register_utm_tracking_metabox() {
287
- $meta_box_title_for_utm = __( 'Google Analytics link tracking', 'email-subscribers' );
288
  add_meta_box( 'es_utm', $meta_box_title_for_utm, array( &$this, 'add_utm_tracking_metabox' ), 'es_template', 'side', 'default' );
289
  }
290
 
291
  /**
292
  * Method to add UTM tracking metabox on ES template page
293
- *
294
  * @since 4.6.2
295
  */
296
  public function add_utm_tracking_metabox() {
297
  global $post;
298
  $es_utm_campaign = get_post_meta( $post->ID, 'es_utm_campaign', true );
299
  $es_utm_campaign = ! empty( $es_utm_campaign ) ? $es_utm_campaign : '';
300
- $allowedtags = ig_es_allowed_html_tags_in_esc();
301
 
302
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
303
  /* translators: 1: UTM parameters */
@@ -320,7 +320,7 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
320
  public function save_utm_campaign( $post_id, $post ) {
321
 
322
  if ( ! empty( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'update-post_' . $post_id ) ) {
323
-
324
  $es_utm_campaign = ig_es_get_data( $_POST, 'es_utm_campaign', false );
325
  if ( false !== $es_utm_campaign ) {
326
  update_post_meta( $post_id, 'es_utm_campaign', $es_utm_campaign );
@@ -330,24 +330,24 @@ if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
330
 
331
  /**
332
  * Method to add UTM tracking option in settings.
333
- *
334
  * @param array $fields Setting fields
335
- *
336
  * @return array $fields Setting fields
337
- *
338
  * @since 4.6.2
339
  */
340
  public function add_utm_tracking_option_in_settings( $fields ) {
341
-
342
  // UTM tracking option
343
- $track_utm = array(
344
  'ig_es_track_utm' => array(
345
  'id' => 'ig_es_track_utm',
346
  'name' => __( 'Google Analytics UTM tracking', 'email-subscribers' ),
347
  'info' => __( 'Do you want to automatically add campaign tracking parameters in emails to track performance in Google Analytics? (We recommend keeping it enabled)', 'email-subscribers' ),
348
  'type' => 'checkbox',
349
- 'default' => 'no'
350
- )
351
  );
352
 
353
  $general_fields = $fields['general'];
14
  */
15
 
16
  if ( ! class_exists( 'IG_ES_Premium_Services_UI' ) ) {
17
+
18
  /**
19
  * The premium services-ui specific functionality of the plugin.
 
20
  */
21
  class IG_ES_Premium_Services_UI {
22
 
26
  * @var Onboarding instance
27
  */
28
  protected static $instance = null;
29
+
30
  /**
31
  * Initialize the class and set its properties.
32
  *
35
  public function __construct() {
36
  add_action( 'init', array( $this, 'init' ) );
37
  }
38
+
39
  /**
40
  * Get class instance.
41
+ *
42
  * @since 4.6.1
43
  */
44
  public static function instance() {
49
  }
50
  /**
51
  * Method to hook required action/filters to show ui components used in premium services.
52
+ *
53
  * @since 4.6.1
54
  */
55
  public function init() {
56
 
57
  // Add ui components only if trial is valid or user is a premium user.
58
  if ( ES()->is_trial_valid() || ES()->is_premium() ) {
59
+
60
  // Add UI for CSS inliner only if service is valid.
61
  if ( ES()->validate_service_request( array( 'css_inliner' ) ) ) {
62
  add_action( 'ig_es_after_broadcast_left_pan_settings', array( &$this, 'add_custom_css_field' ) );
95
  </div>
96
  <?php
97
  }
98
+
99
  /**
100
  * Add Custom CSS block for ES Template
101
  *
117
  </p>
118
  <?php
119
  }
120
+
121
  /**
122
  * Hooked to save_post WordPress action
123
  * Update ES Template data
146
  if ( 'es_template' != $post->post_type ) {
147
  return;
148
  }
149
+
150
  if ( ! empty( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'update-post_' . $post_id ) ) {
151
  // Get custom CSS code. Don't sanitize it since it removes CSS code.
152
  $es_custom_css = ig_es_get_data( $_POST, 'es_custom_css', false, false );
162
  do_action( 'ig_es_save_template', $post_id, $post_id );
163
  }
164
  }
165
+
166
  /**
167
  * Method to add metaboxes
168
+ *
169
  * @since 4.6.1
170
  */
171
  public function add_metaboxes() {
172
  add_meta_box( 'es_spam', __( 'Get Spam Score', 'email-subscribers' ), array( &$this, 'add_spam_score_metabox' ), 'es_template', 'side', 'default' );
173
  }
174
+
175
  /**
176
  * Method to add spam score metabox
177
+ *
178
  * @since 4.6.1
179
  */
180
  public function add_spam_score_metabox() {
192
  </div>
193
  <?php
194
  }
195
+
196
  /**
197
  * Method to show left pan fields in broadcast summary section.
198
  *
199
  * @param array $broadcast_data Broadcast data
200
  *
201
  * @since 4.4.7
 
202
  */
203
  public function add_check_spam_score_button( $broadcast_data = array() ) {
204
  ?>
206
  <span class="pt-3 text-sm font-medium leading-5 text-gray-700"><?php echo esc_html__( 'Get Spam Score', 'email-subscribers' ); ?> </span>
207
  <button type="button" id="spam_score"
208
  class="float-right es_spam rounded-md border text-indigo-600 border-indigo-500 text-sm leading-5 font-medium transition ease-in-out duration-150 select-none inline-flex justify-center hover:text-indigo-500 hover:border-indigo-600 hover:shadow-md focus:outline-none focus:shadow-outline-indigo focus:shadow-lg px-3 py-1">
209
+ <?php
210
+ echo esc_html__(
211
+ 'Check',
212
+ 'email-subscribers'
213
+ );
214
  ?>
215
  </button>
216
  <img src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/spinner-2x.gif" class="es-loader-img inline-flex align-middle pl-2 h-5 w-7" style="display:none;"/>
251
  * @return void
252
  */
253
  public function add_broadcast_utm_tracking_option( $broadcast_data = array() ) {
254
+ $enable_utm_tracking = ! empty( $broadcast_data['meta']['enable_utm_tracking'] ) ? $broadcast_data['meta']['enable_utm_tracking'] : get_option( 'ig_es_track_utm', 'no' );
255
 
256
  $campaign_name = ! empty( $broadcast_data['meta']['es_utm_campaign'] ) ? $broadcast_data['meta']['es_utm_campaign'] : '';
257
 
280
 
281
  /**
282
  * Method to register UTM tracking side metabox on ES template page
283
+ *
284
  * @since 4.6.2
285
  */
286
  public function register_utm_tracking_metabox() {
287
+ $meta_box_title_for_utm = __( 'Google Analytics link tracking', 'email-subscribers' );
288
  add_meta_box( 'es_utm', $meta_box_title_for_utm, array( &$this, 'add_utm_tracking_metabox' ), 'es_template', 'side', 'default' );
289
  }
290
 
291
  /**
292
  * Method to add UTM tracking metabox on ES template page
293
+ *
294
  * @since 4.6.2
295
  */
296
  public function add_utm_tracking_metabox() {
297
  global $post;
298
  $es_utm_campaign = get_post_meta( $post->ID, 'es_utm_campaign', true );
299
  $es_utm_campaign = ! empty( $es_utm_campaign ) ? $es_utm_campaign : '';
300
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
301
 
302
  add_filter( 'safe_style_css', 'ig_es_allowed_css_style' );
303
  /* translators: 1: UTM parameters */
320
  public function save_utm_campaign( $post_id, $post ) {
321
 
322
  if ( ! empty( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'update-post_' . $post_id ) ) {
323
+
324
  $es_utm_campaign = ig_es_get_data( $_POST, 'es_utm_campaign', false );
325
  if ( false !== $es_utm_campaign ) {
326
  update_post_meta( $post_id, 'es_utm_campaign', $es_utm_campaign );
330
 
331
  /**
332
  * Method to add UTM tracking option in settings.
333
+ *
334
  * @param array $fields Setting fields
335
+ *
336
  * @return array $fields Setting fields
337
+ *
338
  * @since 4.6.2
339
  */
340
  public function add_utm_tracking_option_in_settings( $fields ) {
341
+
342
  // UTM tracking option
343
+ $track_utm = array(
344
  'ig_es_track_utm' => array(
345
  'id' => 'ig_es_track_utm',
346
  'name' => __( 'Google Analytics UTM tracking', 'email-subscribers' ),
347
  'info' => __( 'Do you want to automatically add campaign tracking parameters in emails to track performance in Google Analytics? (We recommend keeping it enabled)', 'email-subscribers' ),
348
  'type' => 'checkbox',
349
+ 'default' => 'no',
350
+ ),
351
  );
352
 
353
  $general_fields = $fields['general'];
lite/includes/pro-features.php CHANGED
@@ -15,18 +15,18 @@ add_action( 'ig_es_sync_users_tabs_wpforms', 'ig_es_add_wpforms_tab_settings' );
15
  add_action( 'ig_es_sync_users_tabs_ninja_forms', 'ig_es_add_ninja_forms_tab_settings' );
16
  add_action( 'ig_es_sync_users_tabs_edd', 'ig_es_add_edd_tab_settings' );
17
 
18
- add_action( 'ig_es_workflows_integration', 'ig_es_workflows_integration_metabox', 10 , 1 );
19
- add_filter( 'ig_es_display_hidden_workflow_metabox', 'ig_es_show_hidden_workflow_metabox', 10, 1 );
20
 
21
  add_action( 'edit_form_advanced', 'add_spam_score_utm_link' );
22
 
23
  add_action( 'ig_es_add_additional_options', 'ig_es_add_captcha_option', 10, 1 );
24
- add_action( 'ig_es_after_broadcast_content_left_pan_settings', 'ig_es_additional_send_email_option');
25
  add_action( 'ig_es_after_broadcast_tracking_options_settings', 'ig_es_additional_options', 11 );
26
- //add_action( 'ig_es_broadcast_scheduling_options_settings', 'ig_es_additional_schedule_option');
27
- //add_action( 'ig_es_after_broadcast_right_pan_settings', 'ig_es_additional_spam_score_option');
28
  add_action( 'ig_es_add_multilist_options', 'ig_es_additional_multilist_and_post_digest' );
29
- add_action( 'ig_es_view_report_data', 'ig_es_view_additional_reports_data');
30
 
31
  // Upsell add attachment feature.
32
  add_action( 'media_buttons', 'ig_es_upsell_add_attachment_feature' );
@@ -48,14 +48,15 @@ add_filter( 'ig_es_contacts_bulk_action', 'ig_es_upsell_contacts_bulk_action' );
48
  */
49
  function ig_es_mailers_promo( $mailers ) {
50
 
51
- if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
52
 
53
  $mailers['smtp'] = array(
54
  'name' => 'SMTP',
55
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/smtp.png',
56
  'is_premium' => true,
57
- 'url' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'smtp_mailer' )
58
- )
 
59
  );
60
 
61
  }
@@ -67,54 +68,59 @@ function ig_es_mailers_promo( $mailers ) {
67
  'name' => 'Amazon SES',
68
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/aws.svg',
69
  'is_premium' => true,
70
- 'url' => ES_Common::get_utm_tracking_url( array(
71
- 'url' => 'https://www.icegram.com/documentation/how-to-configure-amazon-ses-to-send-emails-in-the-email-subscribers-plugin/',
72
- 'utm_medium' => 'amazon_ses_mailer'
73
- )
74
- ),
 
75
  ),
76
- 'Mailgun' => array(
77
  'name' => 'Mailgun',
78
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/mailgun.svg',
79
  'is_premium' => true,
80
- 'url' => ES_Common::get_utm_tracking_url( array(
81
- 'url' => 'https://www.icegram.com/documentation/how-to-configure-mailgun-to-send-emails-in-the-email-subscribers-plugin/',
82
- 'utm_medium' => 'mailgun_mailer'
83
- )
84
- ),
 
85
  ),
86
- 'SendGrid' => array(
87
  'name' => 'SendGrid',
88
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/sendgrid.svg',
89
  'is_premium' => true,
90
- 'url' => ES_Common::get_utm_tracking_url( array(
91
- 'url' => 'https://www.icegram.com/documentation/how-to-configure-sendgrid-to-send-emails-in-the-email-subscribers-plugin/',
92
- 'utm_medium' => 'sendgrid_mailer'
93
- )
94
- ),
 
95
  ),
96
- 'SparkPost' => array(
97
  'name' => 'SparkPost',
98
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/sparkpost.png',
99
  'is_premium' => true,
100
- 'url' => ES_Common::get_utm_tracking_url( array(
101
- 'url' => 'https://www.icegram.com/documentation/how-to-configure-sparkpost-to-send-emails-in-the-email-subscribers-plugin/',
102
- 'utm_medium' => 'sparkpost_mailer'
103
- )
104
- ),
 
105
  ),
106
- 'Postmark' => array(
107
  'name' => 'Postmark',
108
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/postmark.png',
109
  'is_premium' => true,
110
- 'url' => ES_Common::get_utm_tracking_url( array(
111
- 'url' => 'https://www.icegram.com/documentation/how-to-configure-postmark-to-send-emails-in-the-email-subscribers-plugin/',
112
- 'utm_medium' => 'postmark_mailer'
113
- )
114
- ),
 
115
  ),
116
  );
117
- $mailers = array_merge( $mailers, $pro_mailers );
118
 
119
  }
120
 
@@ -141,12 +147,12 @@ function render_user_permissions_settings_fields_premium() {
141
  <div class="text-center py-3 lg:px-4">
142
  <div class="p-2 bg-indigo-800 items-center text-indigo-100 leading-none lg:rounded-full flex lg:inline-flex mx-4 leading-normal" role="alert">
143
  <span class="font-semibold text-left flex-auto">
144
- <?php esc_html_e( 'Customize user roles permissions with ', 'email-subscribers'); ?><a href="<?php echo esc_url( $url ); ?>" target="_blank" class="text-indigo-400"><?php esc_html_e( 'Email Subscribers PRO', 'email-subscribers'); ?></a>
145
  </span>
146
  </div>
147
  </div>
148
 
149
- <p class="py-2 text-sm font-normal text-gray-500"><?php echo esc_html__('You can allow different user roles access to different operations within Email Subscribers plugin. Please select which roles should have what access below.', 'email-subscribers' ); ?> </p>
150
  <table class="min-w-full rounded-lg">
151
  <thead>
152
  <tr class="bg-gray-100 leading-4 text-gray-500 tracking-wider">
@@ -160,7 +166,7 @@ function render_user_permissions_settings_fields_premium() {
160
  </tr>
161
  </thead>
162
  <tbody class="bg-white">
163
- <?php
164
  foreach ( $roles as $key => $value ) {
165
  ?>
166
  <tr class="border-b border-gray-200">
@@ -212,8 +218,11 @@ function render_user_permissions_settings_fields_premium() {
212
  */
213
  function ig_es_add_settings_tabs( $es_settings_tabs ) {
214
 
215
- if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
216
- $es_settings_tabs['user_roles'] = array( 'icon' => '<svg class="w-6 h-6 inline -mt-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path></svg>', 'name' => __( 'Access Control', 'email-subscribers' ) );
 
 
 
217
  }
218
 
219
  return $es_settings_tabs;
@@ -228,17 +237,17 @@ function ig_es_add_settings_tabs( $es_settings_tabs ) {
228
  */
229
  function ig_es_add_upsale( $fields ) {
230
 
231
- if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
232
 
233
  $utm_args = array(
234
- 'utm_medium' => 'track_clicks'
235
  );
236
 
237
  $general_fields = $fields['general'];
238
- $premium_url = ES_Common::get_utm_tracking_url( $utm_args );
239
  // General Settings
240
  $general_settings_field = array(
241
- 'ig_es_track_link_click' => array(
242
  'id' => 'ig_es_track_link_click_p',
243
  'name' => __( 'Track clicks', 'email-subscribers' ),
244
  'info' => __( 'Do you want to track when people click links in your emails? (We recommend keeping it enabled)', 'email-subscribers' ),
@@ -249,32 +258,32 @@ function ig_es_add_upsale( $fields ) {
249
  'disabled' => true,
250
  /* translators: %s: Icegram Pricing page url with utm tracking */
251
  'upgrade_title' => __( 'Track key insight behaviour with PRO', 'email-subscribers' ),
252
- 'upgrade_desc' => __( 'Enable Link Tracking, UTM tracking and understand customer behavior to plan your next campaign accordingly.', 'email-subscribers' )
253
  ),
254
 
255
  'ig_es_intermediate_unsubscribe_page' => array(
256
- 'id' => 'ig_es_intermediate_unsubscribe_page_p',
257
- 'name' => __( 'Allow user to select list(s) while unsubscribing', 'email-subscribers' ),
258
- 'info' => __( 'Enabling this will let users unsubscribe from multiple lists at once. (We recommend keeping it enabled)', 'email-subscribers'),
259
- 'type' => 'checkbox',
260
- 'default' => 'no',
261
- 'is_premium' => true,
262
- 'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'intermediate_unsubscribe_page' ) ),
263
- 'disabled' => true,
264
- ),
265
 
266
- 'ig_es_opt_in_consent' => array(
267
  'id' => 'ig_es_opt_in_consent_p',
268
  'name' => __( 'Nudge people to subscribe while leaving a comment or placing an order?', 'email-subscribers' ),
269
  'info' => __( 'Adds a checkbox to subscribe when people post a comment or checkout (if you&rsquo;re using WooCommerce).', 'email-subscribers' ),
270
  'sub_fields' => array(
271
  'ig_es_show_opt_in_consent' => array(
272
- 'id' => 'ig_es_show_opt_in_consent_p',
273
- 'name' => '',
274
- 'info' => __( '(toggle to enable this)', 'email-subscribers' ),
275
- 'type' => 'checkbox',
276
- 'default' => 'no',
277
- 'disabled' => true,
278
  ),
279
  'ig_es_opt_in_consent_text' => array(
280
  'type' => 'textarea',
@@ -284,29 +293,29 @@ function ig_es_add_upsale( $fields ) {
284
  'default' => __( 'Subscribe to our email updates as well.', 'email-subscribers' ),
285
  'id' => 'ig_es_opt_in_consent_text_p',
286
  'name' => __( 'Opt-in consent text', 'email-subscribers' ),
287
- 'disabled' => true,
288
  ),
289
  ),
290
- 'is_premium' => true,
291
- 'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'opt_in_consent_text' ) ),
292
- 'disabled' => true,
293
  ),
294
  );
295
-
296
  $general_fields = ig_es_array_insert_after( $general_fields, 'ig_es_track_email_opens', $general_settings_field );
297
 
298
- if ( ES()->can_upsell_features( array( 'lite', 'starter' ) ) ) {
299
 
300
  $track_utm = array(
301
- 'ig_es_track_utm' => array(
302
- 'id' => 'ig_es_track_utm_p',
303
- 'name' => __( 'Google Analytics UTM tracking', 'email-subscribers' ),
304
- 'info' => __( 'Do you want to automatically add campaign tracking parameters in emails to track performance in Google Analytics? (We recommend keeping it enabled)', 'email-subscribers' ),
305
- 'type' => 'checkbox',
306
- 'default' => 'no',
307
- 'is_premium' => true,
308
- 'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'utm_tracking' ) ),
309
- 'disabled' => true,
310
  ),
311
 
312
  );
@@ -316,24 +325,24 @@ function ig_es_add_upsale( $fields ) {
316
  $fields['general'] = $general_fields;
317
  }
318
 
319
- if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
320
 
321
  $utm_args = array(
322
- 'utm_medium' => 'enable_captcha'
323
  );
324
 
325
  $premium_url = ES_Common::get_utm_tracking_url( $utm_args );
326
 
327
  // Security Settings
328
  $fake_domains['ig_es_enable_known_attackers_domains'] = array(
329
- 'id' => 'ig_es_enable_known_attackers_domains_p',
330
- 'name' => __( 'Block known attackers', 'email-subscribers' ),
331
- 'info' => __( 'Stop spam bot attacker domains from signing up. Icegram maintains a blacklist of such attackers and enabling this option will keep the blacklist updated.', 'email-subscribers' ),
332
- 'type' => 'checkbox',
333
- 'default' => 'no',
334
- 'is_premium' => true,
335
- 'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'known_attackers' ) ),
336
- 'disabled' => true,
337
  /* translators: %s: Icegram Pricing page url with utm tracking */
338
  'upgrade_title' => __( 'Prevent spam attacks with PRO', 'email-subscribers' ),
339
  'upgrade_desc' => __( 'Secure your list from known spam bot attacker domains, fake email addresses and bot signups.', 'email-subscribers' ),
@@ -347,19 +356,19 @@ function ig_es_add_upsale( $fields ) {
347
  'default' => 'no',
348
  'is_premium' => true,
349
  'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'disposable_domains' ) ),
350
- 'disabled' => true
351
  );
352
 
353
- //add captcha setting
354
  $field_captcha['enable_captcha'] = array(
355
- 'id' => 'ig_es_enable_captcha_p',
356
- 'name' => __( 'Enable Captcha', 'email-subscribers' ),
357
- 'info' => __( 'Prevent bot signups even further. Set default captcha option for new subscription forms.', 'email-subscribers' ),
358
- 'type' => 'checkbox',
359
- 'default' => 'no',
360
- 'is_premium' => true,
361
- 'link' => $premium_url,
362
- 'disabled' => true,
363
  );
364
 
365
  $fields['security_settings'] = array_merge( $fields['security_settings'], $fake_domains, $managed_blocked_domains, $field_captcha );
@@ -369,26 +378,26 @@ function ig_es_add_upsale( $fields ) {
369
  'id' => 'ig_es_user_roles',
370
  'name' => '',
371
  'type' => 'html',
372
- 'html' => render_user_permissions_settings_fields_premium()
373
- )
374
  );
375
 
376
  }
377
 
378
- if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
379
  $track_ip_address['ig_es_track_ip_address'] = array(
380
- 'id' => 'ig_es_track_ip_address_p',
381
- 'name' => __( 'Track IP address', 'email-subscribers' ),
382
- 'info' => __( 'Record user\'s IP address on subscription.', 'email-subscribers' ),
383
- 'type' => 'checkbox',
384
- 'default' => 'no',
385
- 'is_premium' => true,
386
- 'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'ip_tracking' ) ),
387
- 'disabled' => true,
388
- /* translators: %s: Icegram Pricing page url with utm tracking */
389
- 'upgrade_title' => __( 'Track subscribers IP addresses with PRO', 'email-subscribers' ),
390
- 'upgrade_desc' => __( 'Enable IP tracking to store IP addresses and country name of subscribers. With this, you can target campaigns like Broadcasts, Sequences to subscribers from specific countries.', 'email-subscribers' ),
391
- );
392
 
393
  $fields['security_settings'] = array_merge( $fields['security_settings'], $track_ip_address );
394
  }
@@ -400,12 +409,12 @@ function ig_es_add_sync_users_tabs( $tabs ) {
400
  global $ig_es_tracker;
401
 
402
  // Show integrations only if ES Premium is not installed.
403
- if ( ! ES()->is_starter() ) {
404
 
405
  $tabs['comments'] = array(
406
  'name' => __( 'Comments', 'email-subscribers' ),
407
  'indicator_option' => 'ig_es_show_sync_comment_users_indicator',
408
- 'indicator_label' => 'Starter'
409
  );
410
 
411
  $woocommerce_plugin = 'woocommerce/woocommerce.php';
@@ -416,7 +425,7 @@ function ig_es_add_sync_users_tabs( $tabs ) {
416
  $tabs['woocommerce'] = array(
417
  'name' => __( 'WooCommerce', 'email-subscribers' ),
418
  'indicator_option' => 'ig_es_show_sync_woocommerce_users_indicator',
419
- 'indicator_label' => 'Starter'
420
  );
421
  }
422
 
@@ -426,7 +435,7 @@ function ig_es_add_sync_users_tabs( $tabs ) {
426
  $tabs['cf7'] = array(
427
  'name' => __( 'Contact Form 7', 'email-subscribers' ),
428
  'indicator_option' => 'ig_es_show_sync_cf7_users_indicator',
429
- 'indicator_label' => 'Starter'
430
  );
431
  }
432
 
@@ -436,7 +445,7 @@ function ig_es_add_sync_users_tabs( $tabs ) {
436
  $tabs['wpforms'] = array(
437
  'name' => __( 'WPForms', 'email-subscribers' ),
438
  'indicator_option' => 'ig_es_show_sync_wpforms_users_indicator',
439
- 'indicator_label' => 'Starter'
440
  );
441
  }
442
 
@@ -446,7 +455,7 @@ function ig_es_add_sync_users_tabs( $tabs ) {
446
  $tabs['give'] = array(
447
  'name' => __( 'Give', 'email-subscribers' ),
448
  'indicator_option' => 'ig_es_show_sync_give_users_indicator',
449
- 'indicator_label' => 'Starter'
450
  );
451
  }
452
 
@@ -456,7 +465,7 @@ function ig_es_add_sync_users_tabs( $tabs ) {
456
  $tabs['ninja_forms'] = array(
457
  'name' => __( 'Ninja Forms', 'email-subscribers' ),
458
  'indicator_option' => 'ig_es_show_sync_ninja_forms_users_indicator',
459
- 'indicator_label' => 'Starter'
460
  );
461
  }
462
 
@@ -466,10 +475,9 @@ function ig_es_add_sync_users_tabs( $tabs ) {
466
  $tabs['edd'] = array(
467
  'name' => __( 'EDD', 'email-subscribers' ),
468
  'indicator_option' => 'ig_es_show_sync_edd_users_indicator',
469
- 'indicator_label' => 'Starter'
470
  );
471
  }
472
-
473
  }
474
 
475
  return $tabs;
@@ -486,7 +494,7 @@ function ig_es_add_comments_tab_settings( $tab_options ) {
486
  */
487
 
488
  $info = array(
489
- 'type' => 'info'
490
  );
491
 
492
  ob_start();
@@ -496,9 +504,12 @@ function ig_es_add_comments_tab_settings( $tab_options ) {
496
  <p><?php esc_html_e( 'Quickly add to your mailing list when someone post a comment on your website.', 'email-subscribers' ); ?></p>
497
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
498
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=comment_sync&utm_campaign=es_upsell#sync_comment_users"><?php esc_html_e( 'Email Subscribers Starter', 'email-subscribers' ); ?></a>,
499
- <?php
500
- esc_html_e( 'you will have settings panel where you need to enable Comment user sync and select the list in which you want to add people whenever someone post a
501
- comment.', 'email-subscribers' )
 
 
 
502
  ?>
503
  </p>
504
  <hr>
@@ -529,10 +540,13 @@ function ig_es_add_woocommerce_tab_settings( $tab_options ) {
529
  <p><?php esc_html_e( 'Are you using WooCommerce for your online business? You can use this integration to add to a specific list whenever someone make a purchase from you', 'email-subscribers' ); ?></p>
530
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
531
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=woocommerce_sync&utm_campaign=es_upsell#sync_woocommerce_customers"><?php esc_html_e( 'Email Subscribers Starter', 'email-subscribers' ); ?></a>,
532
- <?php
533
- esc_html_e( 'you will have settings panel where you need to enable WooCommerce sync and select the list in which you want to add people whenever they
 
534
  purchase something
535
- from you.', 'email-subscribers' )
 
 
536
  ?>
537
  </p>
538
  <hr>
@@ -566,9 +580,11 @@ function ig_es_add_cf7_tab_settings( $tab_options ) {
566
  <p><?php esc_html_e( 'Are you using Contact Form 7 for your list building? You can use this integration to add to a specific list whenever new subscribers added from Contact Form 7', 'email-subscribers' ); ?></p>
567
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
568
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=cf7_sync&utm_campaign=es_upsell#sync_cf7_subscribers">
569
- <?php
570
- esc_html_e( 'Email Subscribers Starter',
571
- 'email-subscribers' )
 
 
572
  ?>
573
  </a>, <?php esc_html_e( 'you will have settings panel where you need to enable Contact form 7 sync and select the list in which you want to add people whenever they fill any of the Contact Form.', 'email-subscribers' ); ?></p>
574
  <hr>
@@ -602,9 +618,11 @@ function ig_es_add_give_tab_settings( $tab_options ) {
602
  <p><?php esc_html_e( 'We found that you are using Give WordPress plugin to collect donations. Now, with this integration, you can add your donors to any of your subscriber list and send them Newsletters in future.', 'email-subscribers' ); ?></p>
603
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
604
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a target="_blank" href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=give_sync&utm_campaign=es_upsell#sync_give_donors">
605
- <?php
606
- esc_html_e( 'Email Subscribers Starter',
607
- 'email-subscribers' )
 
 
608
  ?>
609
  </a>, <?php esc_html_e( 'you will have settings panel where you need to enable Give integration and select the list in which you want to add people whenever they make donation.', 'email-subscribers' ); ?></p>
610
  <hr>
@@ -638,9 +656,11 @@ function ig_es_add_wpforms_tab_settings( $tab_options ) {
638
  <p><?php esc_html_e( 'Are you using Give WordPress plugin to collect donations? Want to send Thank You email to them? You can use this integration to be in touch with them.', 'email-subscribers' ); ?></p>
639
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
640
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a target="_blank" href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=wpforms_sync&utm_campaign=es_upsell#sync_wpforms_contacts">
641
- <?php
642
- esc_html_e( 'Email Subscribers Starter',
643
- 'email-subscribers' )
 
 
644
  ?>
645
  </a>, <?php esc_html_e( 'you will have settings panel where you need to enable Give sync and select the list in which you want to add people whenever they make donation.', 'email-subscribers' ); ?></p>
646
  <hr>
@@ -674,9 +694,11 @@ function ig_es_add_ninja_forms_tab_settings( $tab_options ) {
674
  <p><?php esc_html_e( 'We found that you are using Ninja Forms. Want to add your contact to a mailing list? You can use this integration to add your contact to add into mailing list', 'email-subscribers' ); ?></p>
675
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
676
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a target="_blank" href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=ninja_forms_sync&utm_campaign=es_upsell#sync_ninja_forms_contacts">
677
- <?php
678
- esc_html_e( 'Email Subscribers Starter',
679
- 'email-subscribers' )
 
 
680
  ?>
681
  </a>, <?php esc_html_e( 'you will have settings panel where you need to enable Give sync and select the list in which you want to add people whenever they make donation.', 'email-subscribers' ); ?></p>
682
  <hr>
@@ -710,9 +732,11 @@ function ig_es_add_edd_tab_settings( $tab_options ) {
710
  <p><?php esc_html_e( 'We found that you are using EDD to sell digital goods online. You can use this integration to send Newsletters/ Post Notifications to your customers.', 'email-subscribers' ); ?></p>
711
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
712
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a target="_blank" href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=edd_sync&utm_campaign=es_upsell#sync_edd_customers">
713
- <?php
714
- esc_html_e( 'Email Subscribers Starter',
715
- 'email-subscribers' )
 
 
716
  ?>
717
  </a>, <?php esc_html_e( 'you will have settings panel where you need to enable EDD sync and select the list in which you want to add people whenever they purchase something from you.', 'email-subscribers' ); ?></p>
718
  <hr>
@@ -734,26 +758,26 @@ function ig_es_add_edd_tab_settings( $tab_options ) {
734
  }
735
 
736
  function ig_es_workflows_integration_metabox( $page_prefix = '' ) {
737
- if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
738
-
739
  add_meta_box( 'ig_es_workflow_integration_information', __( 'ES PRO Integrations', 'email-subscribers' ), 'ig_es_workflows_integration_upsell', $page_prefix . '_page_es_workflows', 'side', 'default' );
740
  }
741
  }
742
 
743
  function ig_es_show_hidden_workflow_metabox( $es_workflow_metaboxes ) {
744
 
745
- if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
746
  $es_workflow_metaboxes[] = 'ig_es_workflow_integration_description';
747
  }
748
 
749
  return $es_workflow_metaboxes;
750
  }
751
 
752
- function ig_es_workflows_integration_upsell () {
753
-
754
  $utm_args = array(
755
- 'utm_medium' => 'es_workflow_integration'
756
- );
757
 
758
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
759
 
@@ -762,14 +786,14 @@ function ig_es_workflows_integration_upsell () {
762
  'YITH WooCommerce Wishlist',
763
  'Contact Form 7',
764
  'Easy Digital Downloads',
765
- 'Ninja Forms',
766
  'Give WP',
767
  'Ninja Forms',
768
  'WPForms',
769
  'Gravity Forms',
770
  'Forminator',
771
- );
772
-
773
  $upsell_message = '<div class="pt-1.5">';
774
  foreach ( $plugin_integrations as $plugin_name ) {
775
  $upsell_message .= '<div class="flex items-start space-x-3 -ml-8">
@@ -779,12 +803,12 @@ function ig_es_workflows_integration_upsell () {
779
  <p class="text-sm leading-5 py-0.5 text-gray-500 group-hover:text-gray-900 group-focus:text-gray-900 transition ease-in-out duration-150">' . esc_html( $plugin_name ) . '</p>
780
  </div>';
781
  }
782
- $upsell_message .= '</div><br>' . esc_html__( 'Avoid manual actions and make your workflow quick, simple and effortless by integrating popular WordPress plugins with Email Subscribers PRO.', 'email-subscribers');
783
- $upsell_info = array(
784
- 'upgrade_title' => __('Unlock plugin integrations with PRO', 'email-subscribers' ),
785
- 'pricing_url' => $pricing_url,
786
  'upsell_message' => $upsell_message,
787
- 'cta_html' => false,
788
  );
789
  ES_Common::upsell_description_message_box( $upsell_info );
790
  }
@@ -796,7 +820,7 @@ function add_spam_score_utm_link() {
796
  return;
797
  }
798
 
799
- if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
800
  ?>
801
  <script>
802
  jQuery('#submitdiv').after('<div class="es_upsale"><a style="text-decoration:none;" target="_blank" href="https://www.icegram.com/documentation/how-ready-made-template-in-in-email-subscribers-look/?utm_source=in_app&utm_medium=es_template&utm_campaign=es_upsell"><img title="Get readymade templates" style="width:100%;border:0.3em #d46307 solid" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/starter-tmpl.png"/><p style="background: #d46307; color: #FFF; padding: 4px; width: 100%; text-align:center">Get readymade beautiful email templates</p></a></div>');
@@ -814,20 +838,19 @@ function add_spam_score_utm_link() {
814
  */
815
  function ig_es_add_captcha_option( $form_data ) {
816
 
817
- if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
818
 
819
  $utm_args = array(
820
- 'utm_medium' => 'es_form_captcha'
821
  );
822
 
823
-
824
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
825
- $upsell_info = array(
826
- 'upgrade_title' => __('Protect your subscription list now with PRO', 'email-subscribers'),
827
- 'pricing_url' => $pricing_url,
828
  /* translators: 1. Bold tag 2. Bold close tag */
829
- 'upsell_message' => sprintf( __('Get a gatekeeper like %1$sCaptcha%2$s and prevent bot signups from your subscription form.', 'email-subscribers'), '<b class="font-medium text-teal-800">', '</b>' ),
830
- 'cta_html' => false,
831
  );
832
  ?>
833
 
@@ -859,37 +882,37 @@ function ig_es_add_captcha_option( $form_data ) {
859
  <?php ES_Common::upsell_description_message_box( $upsell_info ); ?>
860
  </div>
861
  </div>
862
- <?php
863
  }
864
  }
865
 
866
  function ig_es_additional_multilist_and_post_digest() {
867
 
868
- if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
869
-
870
  $utm_args = array(
871
- 'utm_medium' => 'post_notifications_multiple_lists'
872
  );
873
 
874
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
875
- $upsell_info = array(
876
- 'upgrade_title' => __('Enable multiple lists & post digest with PRO', 'email-subscribers'),
877
- 'pricing_url' => $pricing_url,
878
  'upsell_message' => '<div class="flex items-start space-x-3 -ml-8">
879
  <div class="flex-shrink-0 h-5 w-5 relative flex justify-center">
880
  <span class="block h-1.5 w-1.5 mt-2.5 bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400 transition ease-in-out duration-150"></span>
881
  </div>
882
- <p class="text-sm leading-5 py-0.5 text-gray-500 group-hover:text-gray-900 group-focus:text-gray-900 transition ease-in-out duration-150">' . esc_html__( 'Want to send notification emails to more than one list? You can select multiple list with', 'email-subscribers') . '<b class="font-medium text-teal-800">' . esc_html__('Email Subscribers PRO.', 'email-subscribers') . '</b></p>
883
  </div>
884
 
885
  <div class="flex items-start space-x-3 -ml-8">
886
  <div class="flex-shrink-0 h-5 w-5 relative flex justify-center">
887
  <span class="block h-1.5 w-1.5 mt-2.5 bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400 transition ease-in-out duration-150"></span>
888
  </div>
889
- <p class="text-sm leading-5 py-0.5 text-gray-500 group-hover:text-gray-900 group-focus:text-gray-900 transition ease-in-out duration-150">' . esc_html__( 'With post digest, improve post notification by sending one notification for multiple post, schedule it to what you feel is the best time and leave it on the plugin.', 'email-subscribers') .
890
  '</p>
891
  </div>',
892
- 'cta_html' => false,
893
  );
894
  ?>
895
  <table>
@@ -936,14 +959,14 @@ function ig_es_additional_multilist_and_post_digest() {
936
 
937
  </tr>
938
  </table>
939
- <?php
940
  }
941
 
942
  }
943
 
944
  function ig_es_additional_send_email_option() {
945
 
946
- if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
947
  ?>
948
 
949
  <div>
@@ -958,30 +981,30 @@ function ig_es_additional_send_email_option() {
958
  </div>
959
  </div>
960
  </div>
961
- <?php
962
  }
963
  }
964
 
965
- function ig_es_additional_options() {
966
  ?>
967
 
968
- <?php
969
- if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
970
  $utm_args = array(
971
- 'utm_medium' => 'broadcast_summary'
972
  );
973
 
974
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
975
- $upsell_info = array(
976
- 'upgrade_title' => __('Reduce the possibility to land in spam with PRO', 'email-subscribers'),
977
- 'pricing_url' => $pricing_url,
978
- 'upsell_message' => __('Build your brand, track your links with the help of Link tracking, UTM tracking and schedule your next broadcast accordingly. Also prevent your emails from landing into spam by checking its spam score'),
979
- 'cta_html' => false,
980
  );
981
  ?>
982
  <div class="flex w-full pt-2">
983
  <div class="w-11/12 text-sm font-normal text-gray-600">
984
- <label class="pt-3 text-sm leading-5 text-gray-500 cursor-default"><?php echo esc_html__( 'Link tracking', 'email-subscribers'); ?></label>
985
  <span class="premium-icon"></span>
986
  </div>
987
 
@@ -996,15 +1019,15 @@ function ig_es_additional_options() {
996
  </div>
997
 
998
 
999
- <?php
1000
  }
1001
 
1002
- if ( ES()->can_upsell_features( array( 'lite', 'starter' ) ) ) {
1003
  ?>
1004
 
1005
  <div class="flex w-full pt-3 pb-3 border-b border-gray-200">
1006
  <div class="w-11/12 text-sm font-normal text-gray-600">
1007
- <label class="pt-3 text-sm leading-5 text-gray-500 cursor-default"><?php echo esc_html__( 'UTM tracking', 'email-subscribers'); ?></label>
1008
  <span class="premium-icon"></span>
1009
  </div>
1010
 
@@ -1019,15 +1042,15 @@ function ig_es_additional_options() {
1019
  </div>
1020
 
1021
  <div class="block my-3">
1022
- <label class="pt-3 text-sm leading-5 font-medium text-gray-500 cursor-default"><?php echo esc_html__( 'Get spam score', 'email-subscribers'); ?></label>
1023
  <span class="premium-icon"></span>
1024
  <button type="button" id="spam_score" disabled class="float-right es_spam rounded-md border text-indigo-400 border-indigo-300 text-sm leading-5 font-medium inline-flex justify-center px-3 py-1 cursor-default"><?php echo esc_html__( 'Check', 'email-subscribers' ); ?>
1025
  </button>
1026
  </div>
1027
- <?php
1028
- }
1029
-
1030
- if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1031
  ?>
1032
  <div class="block w-full pt-3 pb-2">
1033
  <span class="block text-sm font-medium leading-5 text-gray-500"><?php echo esc_html__( 'Send options', 'email-subscribers' ); ?></span>
@@ -1041,7 +1064,7 @@ function ig_es_additional_options() {
1041
  <div class="flex pt-4" >
1042
  <div class="flex w-full w-11/12">
1043
  <label class="text-sm font-normal leading-5 text-gray-500 pt-1 cursor-default"><?php echo esc_html__( 'Date', 'email-subscribers' ); ?></label>
1044
- <input class="font-normal text-sm py-1 ml-2 form-input cursor-default" type="text" value="<?php echo esc_attr( date_i18n('Y-m-d') ); ?>" disabled>
1045
  </div>
1046
  <div>
1047
  <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="text-gray-500 w-5 h-5 my-1 ml-2"><path d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
@@ -1050,7 +1073,7 @@ function ig_es_additional_options() {
1050
  <div class="flex pt-3" >
1051
  <div class="flex w-11/12">
1052
  <label class="text-sm font-normal leading-5 text-gray-500 pt-1 cursor-default"><?php echo esc_html__( 'Time', 'email-subscribers' ); ?></label>
1053
- <input class=" font-normal text-sm py-1 ml-2 form-input cursor-default" type="text" value="<?php echo esc_attr( date_i18n('h:i A') ); ?>" disabled>
1054
 
1055
  </div>
1056
  <div>
@@ -1060,7 +1083,7 @@ function ig_es_additional_options() {
1060
  <div class="pb-3">
1061
  <div class="block px-2 py-2 mt-4 bg-gray-200 rounded-md ">
1062
  <h3 class="text-gray-400 text-sm font-normal cursor-default"><?php echo esc_html__( 'Local Time: ', 'email-subscribers' ); ?>&nbsp;&nbsp;
1063
- <?php echo esc_attr( date_i18n('Y-m-d H:i A' ) ); ?>
1064
  </h3>
1065
  </div>
1066
  </div>
@@ -1070,7 +1093,7 @@ function ig_es_additional_options() {
1070
  </div>
1071
  </div>
1072
  </div>
1073
- <?php
1074
  }
1075
  }
1076
 
@@ -1081,19 +1104,19 @@ function ig_es_additional_options() {
1081
  * @since 4.5.0
1082
  */
1083
 
1084
- function ig_es_view_additional_reports_data() {
1085
- if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1086
  $utm_args = array(
1087
- 'utm_medium' => 'campaign_insight'
1088
  );
1089
 
1090
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
1091
- $upsell_info = array(
1092
- 'upgrade_title' => __('Get campaign analytics with PRO', 'email-subscribers'),
1093
- 'pricing_url' => $pricing_url,
1094
- /* translators: 1. Bold tag 2. Bold close tag */
1095
- 'upsell_message' => sprintf( __('Want to track some very useful statistics of your campaigns and improve your future campaign ? Upgrade to %1$s Email Subscribers Pro %2$s and measure the effectiveness of your campaigns.', 'email-subscribers'), '<b class="font-medium text-teal-800">', '</b>'),
1096
- 'cta_html' => true,
1097
  );
1098
  ?>
1099
  <div>
@@ -1105,7 +1128,7 @@ function ig_es_view_additional_reports_data() {
1105
  <div class="wrap max-w-7xl cursor-default campaign_open_blur font-sans">
1106
  <div class="flex items-center justify-between">
1107
  <div class="flex-shrink-0">
1108
- <span class="text-xl font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e('Report', 'email-subscribers'); ?><svg class="ml-3 align-middle w-5 h-5 text-indigo-600 inline-block" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" stroke="currentColor"><path d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path></svg></span>
1109
  </div>
1110
  </div>
1111
  <div class="mt-3 pb-2 w-full bg-white rounded-md shadow flex">
@@ -1120,16 +1143,16 @@ function ig_es_view_additional_reports_data() {
1120
  </div>
1121
  <div class="w-full text-gray-600 italic font-medium pt-4 text-sm leading-5 overflow-hidden">
1122
  <p class="pl-6 truncate"><?php esc_html_e( 'Type: ', 'email-subscribers' ); ?>
1123
- <span class="pl-1 font-normal not-italic text-gray-900"><?php esc_html_e( 'Broadcast', 'email-subscribers'); ?></span>
1124
  </p>
1125
  <p class="pl-6 pt-2 truncate"><?php esc_html_e( 'From: ', 'email-subscribers' ); ?>
1126
- <span class="pl-1 font-normal not-italic text-gray-900"><?php echo esc_html('hello@icegram.com', 'email-subscribers'); ?>,</span>
1127
  </p>
1128
  <p class="pl-6 pt-2 truncate"><?php esc_html_e( 'List(s): ', 'email-subscribers' ); ?>
1129
- <span class="pl-1 font-normal not-italic text-gray-900 "><?php esc_html_e('Test, Main ', 'email-subscribers'); ?></span>
1130
  </p>
1131
  <p class="pl-6 pt-2 text-gray-600 "><?php esc_html_e( 'Date: ', 'email-subscribers' ); ?>
1132
- <span class="pl-1 font-normal not-italic text-gray-900"><?php esc_html_e('July 1, 2020 10:00 AM', 'email-subscribers'); ?></span>
1133
  </p>
1134
  </div>
1135
  </div>
@@ -1178,7 +1201,7 @@ function ig_es_view_additional_reports_data() {
1178
 
1179
  <div class="mt-6 mb-4">
1180
  <div class="pt-3">
1181
- <span class="text-left text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e('Open and click activity', 'email-subscribers'); ?></span>
1182
  </div>
1183
  <div class="bg-white mt-2 w-full rounded-md">
1184
  <img style="display: block;" class="mx-auto" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/public/images/link-activity-graph.png"/>
@@ -1187,39 +1210,39 @@ function ig_es_view_additional_reports_data() {
1187
  </div>
1188
  <div class="mt-6 mb-2 flex ">
1189
  <div class="w-1/2 pt-3">
1190
- <span class="text-left text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e('Country Opens', 'email-subscribers'); ?></span>
1191
  </div>
1192
  <div class="pt-3 pl-4">
1193
- <span class="text-left text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e('Mail Client Info', 'email-subscribers'); ?></span>
1194
  </div>
1195
  </div>
1196
- <?php
1197
  $country_opens = array(
1198
  array(
1199
- 'code' => 'US',
1200
- 'country' => 'United States',
1201
- 'open' => 1500,
1202
  ),
1203
- array(
1204
- 'code' => 'AU',
1205
- 'country' => 'Australia',
1206
- 'open' => 1200,
1207
  ),
1208
- array(
1209
- 'code' => 'ES',
1210
- 'country' => 'Spain',
1211
- 'open' => 800,
1212
  ),
1213
- array(
1214
- 'code' => 'FR',
1215
- 'country' => 'France',
1216
- 'open' => 650,
 
 
 
 
 
1217
  ),
1218
- array(
1219
- 'code' => 'RU',
1220
- 'country' => 'Russia',
1221
- 'open' => 144,
1222
- )
1223
  );
1224
  ?>
1225
  <div class="mt-2 mb-4 flex">
@@ -1237,8 +1260,8 @@ function ig_es_view_additional_reports_data() {
1237
  </tr>
1238
  </thead>
1239
  <tbody>
1240
- <?php
1241
- foreach ($country_opens as $country_data) {
1242
  ?>
1243
  <tr class="border-b border-gray-200 text-sm leading-5">
1244
  <td class="mx-4 my-3 px-6 py-1 flag-icon flag-icon-<?php echo esc_html( strtolower( $country_data['code'] ) ); ?>">
@@ -1255,11 +1278,11 @@ function ig_es_view_additional_reports_data() {
1255
  </table>
1256
 
1257
  </div>
1258
- <?php
1259
  $mail_clients = array(
1260
- 'Gmail' => 2294,
1261
- 'Gmail App (Android)' => 1500,
1262
- 'Thunderbird' => 500,
1263
  );
1264
  ?>
1265
  <div class=" flex ml-4 w-1/2 bg-white shadow rounded-md self-start">
@@ -1267,16 +1290,16 @@ function ig_es_view_additional_reports_data() {
1267
  <thead>
1268
  <tr>
1269
  <th class="w-2/3 px-6 py-3 border-b border-gray-200 bg-gray-200 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
1270
- <?php esc_html_e('Mail Client', 'email-subscribers'); ?>
1271
  </th>
1272
  <th class="w-1/3 px-6 py-3 border-b border-gray-200 bg-gray-200 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
1273
- <?php esc_html_e('Opens', 'email-subscribers'); ?>
1274
  </th>
1275
  </tr>
1276
  </thead>
1277
  <tbody>
1278
- <?php
1279
- foreach ($mail_clients as $mail_client => $opens) {
1280
  ?>
1281
  <tr>
1282
  <td class="pl-8 py-3 border-b border-gray-200 text-sm leading-5 text-gray-500">
@@ -1294,26 +1317,26 @@ function ig_es_view_additional_reports_data() {
1294
  </div>
1295
  </div>
1296
  <?php
1297
- $graph_open_data = array (
1298
- array(
1299
- 'title' => __( 'Device Info', 'email-subscribers' ),
1300
- 'graph_img' => 'lite/public/images/device_opens.png',
1301
- ),
1302
 
1303
- array(
1304
- 'title' => __( 'Browser Info', 'email-subscribers' ),
1305
- 'graph_img' => 'lite/public/images/browser_opens.png',
1306
- ),
1307
 
1308
- array(
1309
- 'title' => __( 'OS Info', 'email-subscribers' ),
1310
- 'graph_img' => 'lite/public/images/os_opens.png',
1311
- ),
1312
- );
1313
  ?>
1314
 
1315
  <div class="mt-6 mb-4 grid w-full gap-8 grid-cols-3">
1316
- <?php foreach ( $graph_open_data as $data) { ?>
1317
  <div class="w-full">
1318
  <p class="pt-3 text-lg font-medium leading-7 tracking-wide text-gray-600"><?php echo esc_html( $data['title'] ); ?></p>
1319
  <div class="relative mt-2">
@@ -1325,14 +1348,14 @@ function ig_es_view_additional_reports_data() {
1325
 
1326
 
1327
  <div class="mt-6 mb-2">
1328
- <span class="text-left text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e('Link Activity', 'email-subscribers'); ?></span>
1329
  </div>
1330
  <div class="mt-2 mb-4 flex">
1331
  <div class="flex w-full bg-white shadow rounded-md break-words self-start">
1332
  <table class="w-full table-fixed">
1333
  <thead>
1334
  <tr>
1335
- <th class="w-3/5 px-6 py-3 border-b border-gray-200 bg-gray-200 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider"><?php echo esc_html__( 'Link (URL)', 'email-subscribers'); ?>
1336
  </th>
1337
  <th class=" w-1/5 px-6 py-3 border-b border-gray-200 bg-gray-200 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider"><?php echo esc_html__( 'Unique Clicks', 'email-subscribers' ); ?>
1338
  </th>
@@ -1343,8 +1366,8 @@ function ig_es_view_additional_reports_data() {
1343
  <tbody>
1344
  <tr>
1345
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-900">
1346
- <?php
1347
- echo esc_html('https://www.icegram.com/automate-workflow-and-reduce-chaos/', 'email-subscribers');
1348
  ?>
1349
  </td>
1350
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-600">
@@ -1356,8 +1379,8 @@ function ig_es_view_additional_reports_data() {
1356
  </tr>
1357
  <tr>
1358
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-900">
1359
- <?php
1360
- echo esc_html('https://www.icegram.com/how-to-keep-email-out-of-spam-folder/', 'email-subscribers');
1361
  ?>
1362
  </td>
1363
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-600">
@@ -1369,8 +1392,8 @@ function ig_es_view_additional_reports_data() {
1369
  </tr>
1370
  <tr>
1371
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-900">
1372
- <?php
1373
- echo esc_html('https://www.icegram.com/8-effective-tips-to-grow-your-open-rates/');
1374
  ?>
1375
  </td>
1376
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-600">
@@ -1384,94 +1407,93 @@ function ig_es_view_additional_reports_data() {
1384
  </table>
1385
  </div>
1386
  </div>
1387
- <?php
1388
  $last_open_activity = array(
1389
  array(
1390
- 'code' => 'US',
1391
- 'country' => 'United States',
1392
- 'email' => 'bernardlane@gmail.com' ,
1393
- 'device' => 'desktop' ,
1394
- 'mail_client' => 'Gmail' ,
1395
- 'os' => 'Windows' ,
1396
  ),
1397
  array(
1398
- 'code' => 'US',
1399
- 'country' => 'United States',
1400
- 'email' => 'john@gmail.com' ,
1401
- 'device' => 'desktop' ,
1402
- 'mail_client' => 'Gmail' ,
1403
- 'os' => 'Android' ,
1404
  ),
1405
  array(
1406
- 'code' => 'AU',
1407
- 'country' => 'Australia',
1408
- 'email' => 'pasha@gmail.com' ,
1409
- 'device' => 'mobile' ,
1410
- 'mail_client' => 'Gmail App (Android)' ,
1411
- 'os' => 'Android' ,
1412
  ),
1413
  array(
1414
- 'code' => 'ES',
1415
- 'country' => 'Spain',
1416
- 'email' => 'mark@twone.com' ,
1417
- 'device' => 'mobile' ,
1418
- 'mail_client' => 'Gmail App (Android)' ,
1419
- 'os' => 'Android' ,
1420
  ),
1421
  array(
1422
- 'code' => 'FR',
1423
- 'country' => 'France',
1424
- 'email' => 'smith@gmail.com' ,
1425
- 'device' => 'mobile' ,
1426
- 'mail_client' => 'Gmail App (Android)' ,
1427
- 'os' => 'Android' ,
1428
  ),
1429
  array(
1430
- 'code' => 'AU',
1431
- 'country' => 'Australia',
1432
- 'email' => 'bradtke@gmail.com' ,
1433
- 'device' => 'tablet' ,
1434
- 'mail_client' => 'Gmail' ,
1435
- 'os' => 'Windows' ,
1436
  ),
1437
  array(
1438
- 'code' => 'US',
1439
- 'country' => 'United States',
1440
- 'email' => 'bveum@gmail.com' ,
1441
- 'device' => 'desktop' ,
1442
- 'mail_client' => 'Thunderbird' ,
1443
- 'os' => 'Windows' ,
1444
  ),
1445
  array(
1446
- 'code' => 'RU',
1447
- 'country' => 'Russia',
1448
- 'email' => 'tracy@gmail.com' ,
1449
- 'device' => 'desktop' ,
1450
- 'mail_client' => 'Gmail' ,
1451
- 'os' => 'Windows' ,
1452
  ),
1453
  array(
1454
- 'code' => 'ES',
1455
- 'country' => 'Spain',
1456
- 'email' => 'domenick52@twone.com' ,
1457
- 'device' => 'tablet' ,
1458
- 'mail_client' => 'Gmail' ,
1459
- 'os' => 'Windows' ,
1460
  ),
1461
  array(
1462
- 'code' => 'AU',
1463
- 'country' => 'Australia',
1464
- 'email' => 'stanton@gmail.com' ,
1465
- 'device' => 'desktop' ,
1466
- 'mail_client' => 'Thunderbird' ,
1467
- 'os' => 'Windows' ,
1468
  ),
1469
 
1470
-
1471
  );
1472
  ?>
1473
  <div class="mt-8 mb-2">
1474
- <span class="text-left text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e('Last 10 Open Activity', 'email-subscribers'); ?></span>
1475
  </div>
1476
  <div class="mt-2 mb-2 flex">
1477
  <div class="flex w-full bg-white shadow rounded-md break-all">
@@ -1487,8 +1509,8 @@ function ig_es_view_additional_reports_data() {
1487
  </tr>
1488
  </thead>
1489
  <tbody class="bg-white">
1490
- <?php
1491
- foreach ($last_open_activity as $activity) {
1492
  ?>
1493
  <tr class="border-b border-gray-200 text-sm leading-5 text-gray-500">
1494
  <td class="mx-4 my-3 px-6 py-1 flag-icon flag-icon-<?php echo esc_attr( strtolower( $activity['code'] ) ); ?> ">
@@ -1565,16 +1587,16 @@ function ig_es_view_additional_reports_data() {
1565
  </div>
1566
  </div>
1567
 
1568
- <?php
1569
  }
1570
  }
1571
 
1572
 
1573
  /**
1574
  * Upsell add attachment feature in lite/starter/trial versions.
1575
- *
1576
  * @param string $editor_id Editor ID
1577
- *
1578
  * @since 4.6.7
1579
  */
1580
  function ig_es_upsell_add_attachment_feature( $editor_id ) {
@@ -1598,14 +1620,14 @@ function ig_es_upsell_add_attachment_feature( $editor_id ) {
1598
 
1599
  /**
1600
  * Upsell pro import features
1601
- *
1602
  * @since 4.6.7
1603
  */
1604
  function ig_es_upsell_pro_import_features() {
1605
 
1606
  if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1607
  $utm_args = array(
1608
- 'utm_medium' => 'import_existing_wp_users'
1609
  );
1610
 
1611
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
@@ -1623,14 +1645,14 @@ function ig_es_upsell_pro_import_features() {
1623
  </div>
1624
  </label>
1625
  </a>
1626
- <?php
1627
 
1628
  global $ig_es_tracker;
1629
  $is_woocommerce_active = $ig_es_tracker::is_plugin_activated( 'woocommerce/woocommerce.php' );
1630
  if ( $is_woocommerce_active ) {
1631
-
1632
  $utm_args = array(
1633
- 'utm_medium' => 'import_from_wc_orders'
1634
  );
1635
 
1636
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
@@ -1649,65 +1671,65 @@ function ig_es_upsell_pro_import_features() {
1649
  </div>
1650
  </label>
1651
  </a>
1652
- <?php
1653
  }
1654
  }
1655
  }
1656
 
1657
  /**
1658
  * Upsell campaign Pro rules
1659
- *
1660
  * @param array Campaign rules
1661
- *
1662
  * @return array Campaign rules
1663
- *
1664
  * @since 4.6.12
1665
  */
1666
  function ig_es_upsell_pro_campaign_rules( $campaign_rules = array() ) {
1667
 
1668
  if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1669
-
1670
  $pro_campaign_rules = array(
1671
- 'List' => array(
1672
  array(
1673
  'name' => esc_html__( 'is not in List [PRO]', 'email-subscribers' ),
1674
- 'disabled' => true
1675
  ),
1676
  ),
1677
  'Subscriber' => array(
1678
- array(
1679
  'name' => esc_html__( 'Email [PRO]', 'email-subscribers' ),
1680
- 'disabled' => true
1681
  ),
1682
- array(
1683
  'name' => esc_html__( 'Country [PRO]', 'email-subscribers' ),
1684
- 'disabled' => true
1685
  ),
1686
  ),
1687
- 'Campaign' => array(
1688
- array(
1689
  'name' => esc_html__( 'has received [PRO]', 'email-subscribers' ),
1690
- 'disabled' => true
1691
  ),
1692
- array(
1693
  'name' => esc_html__( 'has not received [PRO]', 'email-subscribers' ),
1694
- 'disabled' => true
1695
  ),
1696
- array(
1697
  'name' => esc_html__( 'has received and opened [PRO]', 'email-subscribers' ),
1698
- 'disabled' => true
1699
  ),
1700
- array(
1701
  'name' => esc_html__( 'has received but not opened [PRO]', 'email-subscribers' ),
1702
- 'disabled' => true
1703
  ),
1704
- array(
1705
  'name' => esc_html__( 'has received and clicked [PRO]', 'email-subscribers' ),
1706
- 'disabled' => true
1707
  ),
1708
- array(
1709
  'name' => esc_html__( 'has received and not clicked [PRO]', 'email-subscribers' ),
1710
- 'disabled' => true
1711
  ),
1712
  ),
1713
  );
@@ -1722,16 +1744,16 @@ function ig_es_upsell_campaign_rules_message() {
1722
 
1723
  if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1724
  $utm_args = array(
1725
- 'utm_medium' => 'broadcast_campaign_rules'
1726
  );
1727
 
1728
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
1729
- $upsell_info = array(
1730
- 'upgrade_title' => __('Send Broadcast to specific audience with PRO', 'email-subscribers'),
1731
- 'pricing_url' => $pricing_url,
1732
- 'upsell_message' => __('Now, you can select multiple lists and also filter your subscribers based on their country, emails and whether they have received, opened or clicked a specific campaign or not and then send Broadcast emails to them.', 'email-subscribers'),
1733
- 'cta_html' => false,
1734
- );
1735
 
1736
  ?>
1737
  <div class="block w-2/3 py-2 px-6 mt-2 ">
@@ -1742,7 +1764,7 @@ function ig_es_upsell_campaign_rules_message() {
1742
  }
1743
 
1744
  function ig_es_upsell_contacts_bulk_action( $actions = array() ) {
1745
-
1746
  if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1747
  $actions['bulk_send_confirmation_email_upsell'] = __( 'Send confirmation email [PRO]', 'email-subscribers' );
1748
  }
15
  add_action( 'ig_es_sync_users_tabs_ninja_forms', 'ig_es_add_ninja_forms_tab_settings' );
16
  add_action( 'ig_es_sync_users_tabs_edd', 'ig_es_add_edd_tab_settings' );
17
 
18
+ add_action( 'ig_es_workflows_integration', 'ig_es_workflows_integration_metabox', 10, 1 );
19
+ add_filter( 'ig_es_display_hidden_workflow_metabox', 'ig_es_show_hidden_workflow_metabox', 10, 1 );
20
 
21
  add_action( 'edit_form_advanced', 'add_spam_score_utm_link' );
22
 
23
  add_action( 'ig_es_add_additional_options', 'ig_es_add_captcha_option', 10, 1 );
24
+ add_action( 'ig_es_after_broadcast_content_left_pan_settings', 'ig_es_additional_send_email_option' );
25
  add_action( 'ig_es_after_broadcast_tracking_options_settings', 'ig_es_additional_options', 11 );
26
+ // add_action( 'ig_es_broadcast_scheduling_options_settings', 'ig_es_additional_schedule_option');
27
+ // add_action( 'ig_es_after_broadcast_right_pan_settings', 'ig_es_additional_spam_score_option');
28
  add_action( 'ig_es_add_multilist_options', 'ig_es_additional_multilist_and_post_digest' );
29
+ add_action( 'ig_es_view_report_data', 'ig_es_view_additional_reports_data' );
30
 
31
  // Upsell add attachment feature.
32
  add_action( 'media_buttons', 'ig_es_upsell_add_attachment_feature' );
48
  */
49
  function ig_es_mailers_promo( $mailers ) {
50
 
51
+ if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
52
 
53
  $mailers['smtp'] = array(
54
  'name' => 'SMTP',
55
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/smtp.png',
56
  'is_premium' => true,
57
+ 'url' => ES_Common::get_utm_tracking_url(
58
+ array( 'utm_medium' => 'smtp_mailer' )
59
+ ),
60
  );
61
 
62
  }
68
  'name' => 'Amazon SES',
69
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/aws.svg',
70
  'is_premium' => true,
71
+ 'url' => ES_Common::get_utm_tracking_url(
72
+ array(
73
+ 'url' => 'https://www.icegram.com/documentation/how-to-configure-amazon-ses-to-send-emails-in-the-email-subscribers-plugin/',
74
+ 'utm_medium' => 'amazon_ses_mailer',
75
+ )
76
+ ),
77
  ),
78
+ 'Mailgun' => array(
79
  'name' => 'Mailgun',
80
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/mailgun.svg',
81
  'is_premium' => true,
82
+ 'url' => ES_Common::get_utm_tracking_url(
83
+ array(
84
+ 'url' => 'https://www.icegram.com/documentation/how-to-configure-mailgun-to-send-emails-in-the-email-subscribers-plugin/',
85
+ 'utm_medium' => 'mailgun_mailer',
86
+ )
87
+ ),
88
  ),
89
+ 'SendGrid' => array(
90
  'name' => 'SendGrid',
91
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/sendgrid.svg',
92
  'is_premium' => true,
93
+ 'url' => ES_Common::get_utm_tracking_url(
94
+ array(
95
+ 'url' => 'https://www.icegram.com/documentation/how-to-configure-sendgrid-to-send-emails-in-the-email-subscribers-plugin/',
96
+ 'utm_medium' => 'sendgrid_mailer',
97
+ )
98
+ ),
99
  ),
100
+ 'SparkPost' => array(
101
  'name' => 'SparkPost',
102
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/sparkpost.png',
103
  'is_premium' => true,
104
+ 'url' => ES_Common::get_utm_tracking_url(
105
+ array(
106
+ 'url' => 'https://www.icegram.com/documentation/how-to-configure-sparkpost-to-send-emails-in-the-email-subscribers-plugin/',
107
+ 'utm_medium' => 'sparkpost_mailer',
108
+ )
109
+ ),
110
  ),
111
+ 'Postmark' => array(
112
  'name' => 'Postmark',
113
  'logo' => ES_PLUGIN_URL . 'lite/admin/images/postmark.png',
114
  'is_premium' => true,
115
+ 'url' => ES_Common::get_utm_tracking_url(
116
+ array(
117
+ 'url' => 'https://www.icegram.com/documentation/how-to-configure-postmark-to-send-emails-in-the-email-subscribers-plugin/',
118
+ 'utm_medium' => 'postmark_mailer',
119
+ )
120
+ ),
121
  ),
122
  );
123
+ $mailers = array_merge( $mailers, $pro_mailers );
124
 
125
  }
126
 
147
  <div class="text-center py-3 lg:px-4">
148
  <div class="p-2 bg-indigo-800 items-center text-indigo-100 leading-none lg:rounded-full flex lg:inline-flex mx-4 leading-normal" role="alert">
149
  <span class="font-semibold text-left flex-auto">
150
+ <?php esc_html_e( 'Customize user roles permissions with ', 'email-subscribers' ); ?><a href="<?php echo esc_url( $url ); ?>" target="_blank" class="text-indigo-400"><?php esc_html_e( 'Email Subscribers PRO', 'email-subscribers' ); ?></a>
151
  </span>
152
  </div>
153
  </div>
154
 
155
+ <p class="py-2 text-sm font-normal text-gray-500"><?php echo esc_html__( 'You can allow different user roles access to different operations within Email Subscribers plugin. Please select which roles should have what access below.', 'email-subscribers' ); ?> </p>
156
  <table class="min-w-full rounded-lg">
157
  <thead>
158
  <tr class="bg-gray-100 leading-4 text-gray-500 tracking-wider">
166
  </tr>
167
  </thead>
168
  <tbody class="bg-white">
169
+ <?php
170
  foreach ( $roles as $key => $value ) {
171
  ?>
172
  <tr class="border-b border-gray-200">
218
  */
219
  function ig_es_add_settings_tabs( $es_settings_tabs ) {
220
 
221
+ if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
222
+ $es_settings_tabs['user_roles'] = array(
223
+ 'icon' => '<svg class="w-6 h-6 inline -mt-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path></svg>',
224
+ 'name' => __( 'Access Control', 'email-subscribers' ),
225
+ );
226
  }
227
 
228
  return $es_settings_tabs;
237
  */
238
  function ig_es_add_upsale( $fields ) {
239
 
240
+ if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
241
 
242
  $utm_args = array(
243
+ 'utm_medium' => 'track_clicks',
244
  );
245
 
246
  $general_fields = $fields['general'];
247
+ $premium_url = ES_Common::get_utm_tracking_url( $utm_args );
248
  // General Settings
249
  $general_settings_field = array(
250
+ 'ig_es_track_link_click' => array(
251
  'id' => 'ig_es_track_link_click_p',
252
  'name' => __( 'Track clicks', 'email-subscribers' ),
253
  'info' => __( 'Do you want to track when people click links in your emails? (We recommend keeping it enabled)', 'email-subscribers' ),
258
  'disabled' => true,
259
  /* translators: %s: Icegram Pricing page url with utm tracking */
260
  'upgrade_title' => __( 'Track key insight behaviour with PRO', 'email-subscribers' ),
261
+ 'upgrade_desc' => __( 'Enable Link Tracking, UTM tracking and understand customer behavior to plan your next campaign accordingly.', 'email-subscribers' ),
262
  ),
263
 
264
  'ig_es_intermediate_unsubscribe_page' => array(
265
+ 'id' => 'ig_es_intermediate_unsubscribe_page_p',
266
+ 'name' => __( 'Allow user to select list(s) while unsubscribing', 'email-subscribers' ),
267
+ 'info' => __( 'Enabling this will let users unsubscribe from multiple lists at once. (We recommend keeping it enabled)', 'email-subscribers' ),
268
+ 'type' => 'checkbox',
269
+ 'default' => 'no',
270
+ 'is_premium' => true,
271
+ 'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'intermediate_unsubscribe_page' ) ),
272
+ 'disabled' => true,
273
+ ),
274
 
275
+ 'ig_es_opt_in_consent' => array(
276
  'id' => 'ig_es_opt_in_consent_p',
277
  'name' => __( 'Nudge people to subscribe while leaving a comment or placing an order?', 'email-subscribers' ),
278
  'info' => __( 'Adds a checkbox to subscribe when people post a comment or checkout (if you&rsquo;re using WooCommerce).', 'email-subscribers' ),
279
  'sub_fields' => array(
280
  'ig_es_show_opt_in_consent' => array(
281
+ 'id' => 'ig_es_show_opt_in_consent_p',
282
+ 'name' => '',
283
+ 'info' => __( '(toggle to enable this)', 'email-subscribers' ),
284
+ 'type' => 'checkbox',
285
+ 'default' => 'no',
286
+ 'disabled' => true,
287
  ),
288
  'ig_es_opt_in_consent_text' => array(
289
  'type' => 'textarea',
293
  'default' => __( 'Subscribe to our email updates as well.', 'email-subscribers' ),
294
  'id' => 'ig_es_opt_in_consent_text_p',
295
  'name' => __( 'Opt-in consent text', 'email-subscribers' ),
296
+ 'disabled' => true,
297
  ),
298
  ),
299
+ 'is_premium' => true,
300
+ 'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'opt_in_consent_text' ) ),
301
+ 'disabled' => true,
302
  ),
303
  );
304
+
305
  $general_fields = ig_es_array_insert_after( $general_fields, 'ig_es_track_email_opens', $general_settings_field );
306
 
307
+ if ( ES()->can_upsell_features( array( 'lite', 'starter' ) ) ) {
308
 
309
  $track_utm = array(
310
+ 'ig_es_track_utm' => array(
311
+ 'id' => 'ig_es_track_utm_p',
312
+ 'name' => __( 'Google Analytics UTM tracking', 'email-subscribers' ),
313
+ 'info' => __( 'Do you want to automatically add campaign tracking parameters in emails to track performance in Google Analytics? (We recommend keeping it enabled)', 'email-subscribers' ),
314
+ 'type' => 'checkbox',
315
+ 'default' => 'no',
316
+ 'is_premium' => true,
317
+ 'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'utm_tracking' ) ),
318
+ 'disabled' => true,
319
  ),
320
 
321
  );
325
  $fields['general'] = $general_fields;
326
  }
327
 
328
+ if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
329
 
330
  $utm_args = array(
331
+ 'utm_medium' => 'enable_captcha',
332
  );
333
 
334
  $premium_url = ES_Common::get_utm_tracking_url( $utm_args );
335
 
336
  // Security Settings
337
  $fake_domains['ig_es_enable_known_attackers_domains'] = array(
338
+ 'id' => 'ig_es_enable_known_attackers_domains_p',
339
+ 'name' => __( 'Block known attackers', 'email-subscribers' ),
340
+ 'info' => __( 'Stop spam bot attacker domains from signing up. Icegram maintains a blacklist of such attackers and enabling this option will keep the blacklist updated.', 'email-subscribers' ),
341
+ 'type' => 'checkbox',
342
+ 'default' => 'no',
343
+ 'is_premium' => true,
344
+ 'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'known_attackers' ) ),
345
+ 'disabled' => true,
346
  /* translators: %s: Icegram Pricing page url with utm tracking */
347
  'upgrade_title' => __( 'Prevent spam attacks with PRO', 'email-subscribers' ),
348
  'upgrade_desc' => __( 'Secure your list from known spam bot attacker domains, fake email addresses and bot signups.', 'email-subscribers' ),
356
  'default' => 'no',
357
  'is_premium' => true,
358
  'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'disposable_domains' ) ),
359
+ 'disabled' => true,
360
  );
361
 
362
+ // add captcha setting
363
  $field_captcha['enable_captcha'] = array(
364
+ 'id' => 'ig_es_enable_captcha_p',
365
+ 'name' => __( 'Enable Captcha', 'email-subscribers' ),
366
+ 'info' => __( 'Prevent bot signups even further. Set default captcha option for new subscription forms.', 'email-subscribers' ),
367
+ 'type' => 'checkbox',
368
+ 'default' => 'no',
369
+ 'is_premium' => true,
370
+ 'link' => $premium_url,
371
+ 'disabled' => true,
372
  );
373
 
374
  $fields['security_settings'] = array_merge( $fields['security_settings'], $fake_domains, $managed_blocked_domains, $field_captcha );
378
  'id' => 'ig_es_user_roles',
379
  'name' => '',
380
  'type' => 'html',
381
+ 'html' => render_user_permissions_settings_fields_premium(),
382
+ ),
383
  );
384
 
385
  }
386
 
387
+ if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
388
  $track_ip_address['ig_es_track_ip_address'] = array(
389
+ 'id' => 'ig_es_track_ip_address_p',
390
+ 'name' => __( 'Track IP address', 'email-subscribers' ),
391
+ 'info' => __( 'Record user\'s IP address on subscription.', 'email-subscribers' ),
392
+ 'type' => 'checkbox',
393
+ 'default' => 'no',
394
+ 'is_premium' => true,
395
+ 'link' => ES_Common::get_utm_tracking_url( array( 'utm_medium' => 'ip_tracking' ) ),
396
+ 'disabled' => true,
397
+ /* translators: %s: Icegram Pricing page url with utm tracking */
398
+ 'upgrade_title' => __( 'Track subscribers IP addresses with PRO', 'email-subscribers' ),
399
+ 'upgrade_desc' => __( 'Enable IP tracking to store IP addresses and country name of subscribers. With this, you can target campaigns like Broadcasts, Sequences to subscribers from specific countries.', 'email-subscribers' ),
400
+ );
401
 
402
  $fields['security_settings'] = array_merge( $fields['security_settings'], $track_ip_address );
403
  }
409
  global $ig_es_tracker;
410
 
411
  // Show integrations only if ES Premium is not installed.
412
+ if ( ! ES()->is_starter() ) {
413
 
414
  $tabs['comments'] = array(
415
  'name' => __( 'Comments', 'email-subscribers' ),
416
  'indicator_option' => 'ig_es_show_sync_comment_users_indicator',
417
+ 'indicator_label' => 'Starter',
418
  );
419
 
420
  $woocommerce_plugin = 'woocommerce/woocommerce.php';
425
  $tabs['woocommerce'] = array(
426
  'name' => __( 'WooCommerce', 'email-subscribers' ),
427
  'indicator_option' => 'ig_es_show_sync_woocommerce_users_indicator',
428
+ 'indicator_label' => 'Starter',
429
  );
430
  }
431
 
435
  $tabs['cf7'] = array(
436
  'name' => __( 'Contact Form 7', 'email-subscribers' ),
437
  'indicator_option' => 'ig_es_show_sync_cf7_users_indicator',
438
+ 'indicator_label' => 'Starter',
439
  );
440
  }
441
 
445
  $tabs['wpforms'] = array(
446
  'name' => __( 'WPForms', 'email-subscribers' ),
447
  'indicator_option' => 'ig_es_show_sync_wpforms_users_indicator',
448
+ 'indicator_label' => 'Starter',
449
  );
450
  }
451
 
455
  $tabs['give'] = array(
456
  'name' => __( 'Give', 'email-subscribers' ),
457
  'indicator_option' => 'ig_es_show_sync_give_users_indicator',
458
+ 'indicator_label' => 'Starter',
459
  );
460
  }
461
 
465
  $tabs['ninja_forms'] = array(
466
  'name' => __( 'Ninja Forms', 'email-subscribers' ),
467
  'indicator_option' => 'ig_es_show_sync_ninja_forms_users_indicator',
468
+ 'indicator_label' => 'Starter',
469
  );
470
  }
471
 
475
  $tabs['edd'] = array(
476
  'name' => __( 'EDD', 'email-subscribers' ),
477
  'indicator_option' => 'ig_es_show_sync_edd_users_indicator',
478
+ 'indicator_label' => 'Starter',
479
  );
480
  }
 
481
  }
482
 
483
  return $tabs;
494
  */
495
 
496
  $info = array(
497
+ 'type' => 'info',
498
  );
499
 
500
  ob_start();
504
  <p><?php esc_html_e( 'Quickly add to your mailing list when someone post a comment on your website.', 'email-subscribers' ); ?></p>
505
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
506
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=comment_sync&utm_campaign=es_upsell#sync_comment_users"><?php esc_html_e( 'Email Subscribers Starter', 'email-subscribers' ); ?></a>,
507
+ <?php
508
+ esc_html_e(
509
+ 'you will have settings panel where you need to enable Comment user sync and select the list in which you want to add people whenever someone post a
510
+ comment.',
511
+ 'email-subscribers'
512
+ )
513
  ?>
514
  </p>
515
  <hr>
540
  <p><?php esc_html_e( 'Are you using WooCommerce for your online business? You can use this integration to add to a specific list whenever someone make a purchase from you', 'email-subscribers' ); ?></p>
541
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
542
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=woocommerce_sync&utm_campaign=es_upsell#sync_woocommerce_customers"><?php esc_html_e( 'Email Subscribers Starter', 'email-subscribers' ); ?></a>,
543
+ <?php
544
+ esc_html_e(
545
+ 'you will have settings panel where you need to enable WooCommerce sync and select the list in which you want to add people whenever they
546
  purchase something
547
+ from you.',
548
+ 'email-subscribers'
549
+ )
550
  ?>
551
  </p>
552
  <hr>
580
  <p><?php esc_html_e( 'Are you using Contact Form 7 for your list building? You can use this integration to add to a specific list whenever new subscribers added from Contact Form 7', 'email-subscribers' ); ?></p>
581
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
582
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=cf7_sync&utm_campaign=es_upsell#sync_cf7_subscribers">
583
+ <?php
584
+ esc_html_e(
585
+ 'Email Subscribers Starter',
586
+ 'email-subscribers'
587
+ )
588
  ?>
589
  </a>, <?php esc_html_e( 'you will have settings panel where you need to enable Contact form 7 sync and select the list in which you want to add people whenever they fill any of the Contact Form.', 'email-subscribers' ); ?></p>
590
  <hr>
618
  <p><?php esc_html_e( 'We found that you are using Give WordPress plugin to collect donations. Now, with this integration, you can add your donors to any of your subscriber list and send them Newsletters in future.', 'email-subscribers' ); ?></p>
619
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
620
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a target="_blank" href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=give_sync&utm_campaign=es_upsell#sync_give_donors">
621
+ <?php
622
+ esc_html_e(
623
+ 'Email Subscribers Starter',
624
+ 'email-subscribers'
625
+ )
626
  ?>
627
  </a>, <?php esc_html_e( 'you will have settings panel where you need to enable Give integration and select the list in which you want to add people whenever they make donation.', 'email-subscribers' ); ?></p>
628
  <hr>
656
  <p><?php esc_html_e( 'Are you using Give WordPress plugin to collect donations? Want to send Thank You email to them? You can use this integration to be in touch with them.', 'email-subscribers' ); ?></p>
657
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
658
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a target="_blank" href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=wpforms_sync&utm_campaign=es_upsell#sync_wpforms_contacts">
659
+ <?php
660
+ esc_html_e(
661
+ 'Email Subscribers Starter',
662
+ 'email-subscribers'
663
+ )
664
  ?>
665
  </a>, <?php esc_html_e( 'you will have settings panel where you need to enable Give sync and select the list in which you want to add people whenever they make donation.', 'email-subscribers' ); ?></p>
666
  <hr>
694
  <p><?php esc_html_e( 'We found that you are using Ninja Forms. Want to add your contact to a mailing list? You can use this integration to add your contact to add into mailing list', 'email-subscribers' ); ?></p>
695
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
696
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a target="_blank" href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=ninja_forms_sync&utm_campaign=es_upsell#sync_ninja_forms_contacts">
697
+ <?php
698
+ esc_html_e(
699
+ 'Email Subscribers Starter',
700
+ 'email-subscribers'
701
+ )
702
  ?>
703
  </a>, <?php esc_html_e( 'you will have settings panel where you need to enable Give sync and select the list in which you want to add people whenever they make donation.', 'email-subscribers' ); ?></p>
704
  <hr>
732
  <p><?php esc_html_e( 'We found that you are using EDD to sell digital goods online. You can use this integration to send Newsletters/ Post Notifications to your customers.', 'email-subscribers' ); ?></p>
733
  <h2><?php esc_html_e( 'How to setup?', 'email-subscribers' ); ?></h2>
734
  <p><?php esc_html_e( 'Once you upgrade to ', 'email-subscribers' ); ?><a target="_blank" href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=edd_sync&utm_campaign=es_upsell#sync_edd_customers">
735
+ <?php
736
+ esc_html_e(
737
+ 'Email Subscribers Starter',
738
+ 'email-subscribers'
739
+ )
740
  ?>
741
  </a>, <?php esc_html_e( 'you will have settings panel where you need to enable EDD sync and select the list in which you want to add people whenever they purchase something from you.', 'email-subscribers' ); ?></p>
742
  <hr>
758
  }
759
 
760
  function ig_es_workflows_integration_metabox( $page_prefix = '' ) {
761
+ if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
762
+
763
  add_meta_box( 'ig_es_workflow_integration_information', __( 'ES PRO Integrations', 'email-subscribers' ), 'ig_es_workflows_integration_upsell', $page_prefix . '_page_es_workflows', 'side', 'default' );
764
  }
765
  }
766
 
767
  function ig_es_show_hidden_workflow_metabox( $es_workflow_metaboxes ) {
768
 
769
+ if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
770
  $es_workflow_metaboxes[] = 'ig_es_workflow_integration_description';
771
  }
772
 
773
  return $es_workflow_metaboxes;
774
  }
775
 
776
+ function ig_es_workflows_integration_upsell() {
777
+
778
  $utm_args = array(
779
+ 'utm_medium' => 'es_workflow_integration',
780
+ );
781
 
782
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
783
 
786
  'YITH WooCommerce Wishlist',
787
  'Contact Form 7',
788
  'Easy Digital Downloads',
789
+ 'Ninja Forms',
790
  'Give WP',
791
  'Ninja Forms',
792
  'WPForms',
793
  'Gravity Forms',
794
  'Forminator',
795
+ );
796
+
797
  $upsell_message = '<div class="pt-1.5">';
798
  foreach ( $plugin_integrations as $plugin_name ) {
799
  $upsell_message .= '<div class="flex items-start space-x-3 -ml-8">
803
  <p class="text-sm leading-5 py-0.5 text-gray-500 group-hover:text-gray-900 group-focus:text-gray-900 transition ease-in-out duration-150">' . esc_html( $plugin_name ) . '</p>
804
  </div>';
805
  }
806
+ $upsell_message .= '</div><br>' . esc_html__( 'Avoid manual actions and make your workflow quick, simple and effortless by integrating popular WordPress plugins with Email Subscribers PRO.', 'email-subscribers' );
807
+ $upsell_info = array(
808
+ 'upgrade_title' => __( 'Unlock plugin integrations with PRO', 'email-subscribers' ),
809
+ 'pricing_url' => $pricing_url,
810
  'upsell_message' => $upsell_message,
811
+ 'cta_html' => false,
812
  );
813
  ES_Common::upsell_description_message_box( $upsell_info );
814
  }
820
  return;
821
  }
822
 
823
+ if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
824
  ?>
825
  <script>
826
  jQuery('#submitdiv').after('<div class="es_upsale"><a style="text-decoration:none;" target="_blank" href="https://www.icegram.com/documentation/how-ready-made-template-in-in-email-subscribers-look/?utm_source=in_app&utm_medium=es_template&utm_campaign=es_upsell"><img title="Get readymade templates" style="width:100%;border:0.3em #d46307 solid" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/admin/images/starter-tmpl.png"/><p style="background: #d46307; color: #FFF; padding: 4px; width: 100%; text-align:center">Get readymade beautiful email templates</p></a></div>');
838
  */
839
  function ig_es_add_captcha_option( $form_data ) {
840
 
841
+ if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
842
 
843
  $utm_args = array(
844
+ 'utm_medium' => 'es_form_captcha',
845
  );
846
 
 
847
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
848
+ $upsell_info = array(
849
+ 'upgrade_title' => __( 'Protect your subscription list now with PRO', 'email-subscribers' ),
850
+ 'pricing_url' => $pricing_url,
851
  /* translators: 1. Bold tag 2. Bold close tag */
852
+ 'upsell_message' => sprintf( __( 'Get a gatekeeper like %1$sCaptcha%2$s and prevent bot signups from your subscription form.', 'email-subscribers' ), '<b class="font-medium text-teal-800">', '</b>' ),
853
+ 'cta_html' => false,
854
  );
855
  ?>
856
 
882
  <?php ES_Common::upsell_description_message_box( $upsell_info ); ?>
883
  </div>
884
  </div>
885
+ <?php
886
  }
887
  }
888
 
889
  function ig_es_additional_multilist_and_post_digest() {
890
 
891
+ if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
892
+
893
  $utm_args = array(
894
+ 'utm_medium' => 'post_notifications_multiple_lists',
895
  );
896
 
897
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
898
+ $upsell_info = array(
899
+ 'upgrade_title' => __( 'Enable multiple lists & post digest with PRO', 'email-subscribers' ),
900
+ 'pricing_url' => $pricing_url,
901
  'upsell_message' => '<div class="flex items-start space-x-3 -ml-8">
902
  <div class="flex-shrink-0 h-5 w-5 relative flex justify-center">
903
  <span class="block h-1.5 w-1.5 mt-2.5 bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400 transition ease-in-out duration-150"></span>
904
  </div>
905
+ <p class="text-sm leading-5 py-0.5 text-gray-500 group-hover:text-gray-900 group-focus:text-gray-900 transition ease-in-out duration-150">' . esc_html__( 'Want to send notification emails to more than one list? You can select multiple list with', 'email-subscribers' ) . '<b class="font-medium text-teal-800">' . esc_html__( 'Email Subscribers PRO.', 'email-subscribers' ) . '</b></p>
906
  </div>
907
 
908
  <div class="flex items-start space-x-3 -ml-8">
909
  <div class="flex-shrink-0 h-5 w-5 relative flex justify-center">
910
  <span class="block h-1.5 w-1.5 mt-2.5 bg-gray-300 rounded-full group-hover:bg-gray-400 group-focus:bg-gray-400 transition ease-in-out duration-150"></span>
911
  </div>
912
+ <p class="text-sm leading-5 py-0.5 text-gray-500 group-hover:text-gray-900 group-focus:text-gray-900 transition ease-in-out duration-150">' . esc_html__( 'With post digest, improve post notification by sending one notification for multiple post, schedule it to what you feel is the best time and leave it on the plugin.', 'email-subscribers' ) .
913
  '</p>
914
  </div>',
915
+ 'cta_html' => false,
916
  );
917
  ?>
918
  <table>
959
 
960
  </tr>
961
  </table>
962
+ <?php
963
  }
964
 
965
  }
966
 
967
  function ig_es_additional_send_email_option() {
968
 
969
+ if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
970
  ?>
971
 
972
  <div>
981
  </div>
982
  </div>
983
  </div>
984
+ <?php
985
  }
986
  }
987
 
988
+ function ig_es_additional_options() {
989
  ?>
990
 
991
+ <?php
992
+ if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
993
  $utm_args = array(
994
+ 'utm_medium' => 'broadcast_summary',
995
  );
996
 
997
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
998
+ $upsell_info = array(
999
+ 'upgrade_title' => __( 'Reduce the possibility to land in spam with PRO', 'email-subscribers' ),
1000
+ 'pricing_url' => $pricing_url,
1001
+ 'upsell_message' => __( 'Build your brand, track your links with the help of Link tracking, UTM tracking and schedule your next broadcast accordingly. Also prevent your emails from landing into spam by checking its spam score' ),
1002
+ 'cta_html' => false,
1003
  );
1004
  ?>
1005
  <div class="flex w-full pt-2">
1006
  <div class="w-11/12 text-sm font-normal text-gray-600">
1007
+ <label class="pt-3 text-sm leading-5 text-gray-500 cursor-default"><?php echo esc_html__( 'Link tracking', 'email-subscribers' ); ?></label>
1008
  <span class="premium-icon"></span>
1009
  </div>
1010
 
1019
  </div>
1020
 
1021
 
1022
+ <?php
1023
  }
1024
 
1025
+ if ( ES()->can_upsell_features( array( 'lite', 'starter' ) ) ) {
1026
  ?>
1027
 
1028
  <div class="flex w-full pt-3 pb-3 border-b border-gray-200">
1029
  <div class="w-11/12 text-sm font-normal text-gray-600">
1030
+ <label class="pt-3 text-sm leading-5 text-gray-500 cursor-default"><?php echo esc_html__( 'UTM tracking', 'email-subscribers' ); ?></label>
1031
  <span class="premium-icon"></span>
1032
  </div>
1033
 
1042
  </div>
1043
 
1044
  <div class="block my-3">
1045
+ <label class="pt-3 text-sm leading-5 font-medium text-gray-500 cursor-default"><?php echo esc_html__( 'Get spam score', 'email-subscribers' ); ?></label>
1046
  <span class="premium-icon"></span>
1047
  <button type="button" id="spam_score" disabled class="float-right es_spam rounded-md border text-indigo-400 border-indigo-300 text-sm leading-5 font-medium inline-flex justify-center px-3 py-1 cursor-default"><?php echo esc_html__( 'Check', 'email-subscribers' ); ?>
1048
  </button>
1049
  </div>
1050
+ <?php
1051
+ }
1052
+
1053
+ if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1054
  ?>
1055
  <div class="block w-full pt-3 pb-2">
1056
  <span class="block text-sm font-medium leading-5 text-gray-500"><?php echo esc_html__( 'Send options', 'email-subscribers' ); ?></span>
1064
  <div class="flex pt-4" >
1065
  <div class="flex w-full w-11/12">
1066
  <label class="text-sm font-normal leading-5 text-gray-500 pt-1 cursor-default"><?php echo esc_html__( 'Date', 'email-subscribers' ); ?></label>
1067
+ <input class="font-normal text-sm py-1 ml-2 form-input cursor-default" type="text" value="<?php echo esc_attr( date_i18n( 'Y-m-d' ) ); ?>" disabled>
1068
  </div>
1069
  <div>
1070
  <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="text-gray-500 w-5 h-5 my-1 ml-2"><path d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
1073
  <div class="flex pt-3" >
1074
  <div class="flex w-11/12">
1075
  <label class="text-sm font-normal leading-5 text-gray-500 pt-1 cursor-default"><?php echo esc_html__( 'Time', 'email-subscribers' ); ?></label>
1076
+ <input class=" font-normal text-sm py-1 ml-2 form-input cursor-default" type="text" value="<?php echo esc_attr( date_i18n( 'h:i A' ) ); ?>" disabled>
1077
 
1078
  </div>
1079
  <div>
1083
  <div class="pb-3">
1084
  <div class="block px-2 py-2 mt-4 bg-gray-200 rounded-md ">
1085
  <h3 class="text-gray-400 text-sm font-normal cursor-default"><?php echo esc_html__( 'Local Time: ', 'email-subscribers' ); ?>&nbsp;&nbsp;
1086
+ <?php echo esc_attr( date_i18n( 'Y-m-d H:i A' ) ); ?>
1087
  </h3>
1088
  </div>
1089
  </div>
1093
  </div>
1094
  </div>
1095
  </div>
1096
+ <?php
1097
  }
1098
  }
1099
 
1104
  * @since 4.5.0
1105
  */
1106
 
1107
+ function ig_es_view_additional_reports_data() {
1108
+ if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1109
  $utm_args = array(
1110
+ 'utm_medium' => 'campaign_insight',
1111
  );
1112
 
1113
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
1114
+ $upsell_info = array(
1115
+ 'upgrade_title' => __( 'Get campaign analytics with PRO', 'email-subscribers' ),
1116
+ 'pricing_url' => $pricing_url,
1117
+ /* translators: 1. Bold tag 2. Bold close tag */
1118
+ 'upsell_message' => sprintf( __( 'Want to track some very useful statistics of your campaigns and improve your future campaign ? Upgrade to %1$s Email Subscribers Pro %2$s and measure the effectiveness of your campaigns.', 'email-subscribers' ), '<b class="font-medium text-teal-800">', '</b>' ),
1119
+ 'cta_html' => true,
1120
  );
1121
  ?>
1122
  <div>
1128
  <div class="wrap max-w-7xl cursor-default campaign_open_blur font-sans">
1129
  <div class="flex items-center justify-between">
1130
  <div class="flex-shrink-0">
1131
+ <span class="text-xl font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e( 'Report', 'email-subscribers' ); ?><svg class="ml-3 align-middle w-5 h-5 text-indigo-600 inline-block" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" stroke="currentColor"><path d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path></svg></span>
1132
  </div>
1133
  </div>
1134
  <div class="mt-3 pb-2 w-full bg-white rounded-md shadow flex">
1143
  </div>
1144
  <div class="w-full text-gray-600 italic font-medium pt-4 text-sm leading-5 overflow-hidden">
1145
  <p class="pl-6 truncate"><?php esc_html_e( 'Type: ', 'email-subscribers' ); ?>
1146
+ <span class="pl-1 font-normal not-italic text-gray-900"><?php esc_html_e( 'Broadcast', 'email-subscribers' ); ?></span>
1147
  </p>
1148
  <p class="pl-6 pt-2 truncate"><?php esc_html_e( 'From: ', 'email-subscribers' ); ?>
1149
+ <span class="pl-1 font-normal not-italic text-gray-900"><?php echo esc_html( 'hello@icegram.com', 'email-subscribers' ); ?>,</span>
1150
  </p>
1151
  <p class="pl-6 pt-2 truncate"><?php esc_html_e( 'List(s): ', 'email-subscribers' ); ?>
1152
+ <span class="pl-1 font-normal not-italic text-gray-900 "><?php esc_html_e( 'Test, Main ', 'email-subscribers' ); ?></span>
1153
  </p>
1154
  <p class="pl-6 pt-2 text-gray-600 "><?php esc_html_e( 'Date: ', 'email-subscribers' ); ?>
1155
+ <span class="pl-1 font-normal not-italic text-gray-900"><?php esc_html_e( 'July 1, 2020 10:00 AM', 'email-subscribers' ); ?></span>
1156
  </p>
1157
  </div>
1158
  </div>
1201
 
1202
  <div class="mt-6 mb-4">
1203
  <div class="pt-3">
1204
+ <span class="text-left text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e( 'Open and click activity', 'email-subscribers' ); ?></span>
1205
  </div>
1206
  <div class="bg-white mt-2 w-full rounded-md">
1207
  <img style="display: block;" class="mx-auto" src="<?php echo esc_url( ES_PLUGIN_URL ); ?>lite/public/images/link-activity-graph.png"/>
1210
  </div>
1211
  <div class="mt-6 mb-2 flex ">
1212
  <div class="w-1/2 pt-3">
1213
+ <span class="text-left text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e( 'Country Opens', 'email-subscribers' ); ?></span>
1214
  </div>
1215
  <div class="pt-3 pl-4">
1216
+ <span class="text-left text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e( 'Mail Client Info', 'email-subscribers' ); ?></span>
1217
  </div>
1218
  </div>
1219
+ <?php
1220
  $country_opens = array(
1221
  array(
1222
+ 'code' => 'US',
1223
+ 'country' => 'United States',
1224
+ 'open' => 1500,
1225
  ),
1226
+ array(
1227
+ 'code' => 'AU',
1228
+ 'country' => 'Australia',
1229
+ 'open' => 1200,
1230
  ),
1231
+ array(
1232
+ 'code' => 'ES',
1233
+ 'country' => 'Spain',
1234
+ 'open' => 800,
1235
  ),
1236
+ array(
1237
+ 'code' => 'FR',
1238
+ 'country' => 'France',
1239
+ 'open' => 650,
1240
+ ),
1241
+ array(
1242
+ 'code' => 'RU',
1243
+ 'country' => 'Russia',
1244
+ 'open' => 144,
1245
  ),
 
 
 
 
 
1246
  );
1247
  ?>
1248
  <div class="mt-2 mb-4 flex">
1260
  </tr>
1261
  </thead>
1262
  <tbody>
1263
+ <?php
1264
+ foreach ( $country_opens as $country_data ) {
1265
  ?>
1266
  <tr class="border-b border-gray-200 text-sm leading-5">
1267
  <td class="mx-4 my-3 px-6 py-1 flag-icon flag-icon-<?php echo esc_html( strtolower( $country_data['code'] ) ); ?>">
1278
  </table>
1279
 
1280
  </div>
1281
+ <?php
1282
  $mail_clients = array(
1283
+ 'Gmail' => 2294,
1284
+ 'Gmail App (Android)' => 1500,
1285
+ 'Thunderbird' => 500,
1286
  );
1287
  ?>
1288
  <div class=" flex ml-4 w-1/2 bg-white shadow rounded-md self-start">
1290
  <thead>
1291
  <tr>
1292
  <th class="w-2/3 px-6 py-3 border-b border-gray-200 bg-gray-200 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
1293
+ <?php esc_html_e( 'Mail Client', 'email-subscribers' ); ?>
1294
  </th>
1295
  <th class="w-1/3 px-6 py-3 border-b border-gray-200 bg-gray-200 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
1296
+ <?php esc_html_e( 'Opens', 'email-subscribers' ); ?>
1297
  </th>
1298
  </tr>
1299
  </thead>
1300
  <tbody>
1301
+ <?php
1302
+ foreach ( $mail_clients as $mail_client => $opens ) {
1303
  ?>
1304
  <tr>
1305
  <td class="pl-8 py-3 border-b border-gray-200 text-sm leading-5 text-gray-500">
1317
  </div>
1318
  </div>
1319
  <?php
1320
+ $graph_open_data = array(
1321
+ array(
1322
+ 'title' => __( 'Device Info', 'email-subscribers' ),
1323
+ 'graph_img' => 'lite/public/images/device_opens.png',
1324
+ ),
1325
 
1326
+ array(
1327
+ 'title' => __( 'Browser Info', 'email-subscribers' ),
1328
+ 'graph_img' => 'lite/public/images/browser_opens.png',
1329
+ ),
1330
 
1331
+ array(
1332
+ 'title' => __( 'OS Info', 'email-subscribers' ),
1333
+ 'graph_img' => 'lite/public/images/os_opens.png',
1334
+ ),
1335
+ );
1336
  ?>
1337
 
1338
  <div class="mt-6 mb-4 grid w-full gap-8 grid-cols-3">
1339
+ <?php foreach ( $graph_open_data as $data ) { ?>
1340
  <div class="w-full">
1341
  <p class="pt-3 text-lg font-medium leading-7 tracking-wide text-gray-600"><?php echo esc_html( $data['title'] ); ?></p>
1342
  <div class="relative mt-2">
1348
 
1349
 
1350
  <div class="mt-6 mb-2">
1351
+ <span class="text-left text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e( 'Link Activity', 'email-subscribers' ); ?></span>
1352
  </div>
1353
  <div class="mt-2 mb-4 flex">
1354
  <div class="flex w-full bg-white shadow rounded-md break-words self-start">
1355
  <table class="w-full table-fixed">
1356
  <thead>
1357
  <tr>
1358
+ <th class="w-3/5 px-6 py-3 border-b border-gray-200 bg-gray-200 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider"><?php echo esc_html__( 'Link (URL)', 'email-subscribers' ); ?>
1359
  </th>
1360
  <th class=" w-1/5 px-6 py-3 border-b border-gray-200 bg-gray-200 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider"><?php echo esc_html__( 'Unique Clicks', 'email-subscribers' ); ?>
1361
  </th>
1366
  <tbody>
1367
  <tr>
1368
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-900">
1369
+ <?php
1370
+ echo esc_html( 'https://www.icegram.com/automate-workflow-and-reduce-chaos/', 'email-subscribers' );
1371
  ?>
1372
  </td>
1373
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-600">
1379
  </tr>
1380
  <tr>
1381
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-900">
1382
+ <?php
1383
+ echo esc_html( 'https://www.icegram.com/how-to-keep-email-out-of-spam-folder/', 'email-subscribers' );
1384
  ?>
1385
  </td>
1386
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-600">
1392
  </tr>
1393
  <tr>
1394
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-900">
1395
+ <?php
1396
+ echo esc_html( 'https://www.icegram.com/8-effective-tips-to-grow-your-open-rates/' );
1397
  ?>
1398
  </td>
1399
  <td class="px-6 py-3 border-b border-gray-200 text-sm leading-5 text-gray-600">
1407
  </table>
1408
  </div>
1409
  </div>
1410
+ <?php
1411
  $last_open_activity = array(
1412
  array(
1413
+ 'code' => 'US',
1414
+ 'country' => 'United States',
1415
+ 'email' => 'bernardlane@gmail.com',
1416
+ 'device' => 'desktop',
1417
+ 'mail_client' => 'Gmail',
1418
+ 'os' => 'Windows',
1419
  ),
1420
  array(
1421
+ 'code' => 'US',
1422
+ 'country' => 'United States',
1423
+ 'email' => 'john@gmail.com',
1424
+ 'device' => 'desktop',
1425
+ 'mail_client' => 'Gmail',
1426
+ 'os' => 'Android',
1427
  ),
1428
  array(
1429
+ 'code' => 'AU',
1430
+ 'country' => 'Australia',
1431
+ 'email' => 'pasha@gmail.com',
1432
+ 'device' => 'mobile',
1433
+ 'mail_client' => 'Gmail App (Android)',
1434
+ 'os' => 'Android',
1435
  ),
1436
  array(
1437
+ 'code' => 'ES',
1438
+ 'country' => 'Spain',
1439
+ 'email' => 'mark@twone.com',
1440
+ 'device' => 'mobile',
1441
+ 'mail_client' => 'Gmail App (Android)',
1442
+ 'os' => 'Android',
1443
  ),
1444
  array(
1445
+ 'code' => 'FR',
1446
+ 'country' => 'France',
1447
+ 'email' => 'smith@gmail.com',
1448
+ 'device' => 'mobile',
1449
+ 'mail_client' => 'Gmail App (Android)',
1450
+ 'os' => 'Android',
1451
  ),
1452
  array(
1453
+ 'code' => 'AU',
1454
+ 'country' => 'Australia',
1455
+ 'email' => 'bradtke@gmail.com',
1456
+ 'device' => 'tablet',
1457
+ 'mail_client' => 'Gmail',
1458
+ 'os' => 'Windows',
1459
  ),
1460
  array(
1461
+ 'code' => 'US',
1462
+ 'country' => 'United States',
1463
+ 'email' => 'bveum@gmail.com',
1464
+ 'device' => 'desktop',
1465
+ 'mail_client' => 'Thunderbird',
1466
+ 'os' => 'Windows',
1467
  ),
1468
  array(
1469
+ 'code' => 'RU',
1470
+ 'country' => 'Russia',
1471
+ 'email' => 'tracy@gmail.com',
1472
+ 'device' => 'desktop',
1473
+ 'mail_client' => 'Gmail',
1474
+ 'os' => 'Windows',
1475
  ),
1476
  array(
1477
+ 'code' => 'ES',
1478
+ 'country' => 'Spain',
1479
+ 'email' => 'domenick52@twone.com',
1480
+ 'device' => 'tablet',
1481
+ 'mail_client' => 'Gmail',
1482
+ 'os' => 'Windows',
1483
  ),
1484
  array(
1485
+ 'code' => 'AU',
1486
+ 'country' => 'Australia',
1487
+ 'email' => 'stanton@gmail.com',
1488
+ 'device' => 'desktop',
1489
+ 'mail_client' => 'Thunderbird',
1490
+ 'os' => 'Windows',
1491
  ),
1492
 
 
1493
  );
1494
  ?>
1495
  <div class="mt-8 mb-2">
1496
+ <span class="text-left text-lg font-medium leading-7 tracking-wide text-gray-600"><?php esc_html_e( 'Last 10 Open Activity', 'email-subscribers' ); ?></span>
1497
  </div>
1498
  <div class="mt-2 mb-2 flex">
1499
  <div class="flex w-full bg-white shadow rounded-md break-all">
1509
  </tr>
1510
  </thead>
1511
  <tbody class="bg-white">
1512
+ <?php
1513
+ foreach ( $last_open_activity as $activity ) {
1514
  ?>
1515
  <tr class="border-b border-gray-200 text-sm leading-5 text-gray-500">
1516
  <td class="mx-4 my-3 px-6 py-1 flag-icon flag-icon-<?php echo esc_attr( strtolower( $activity['code'] ) ); ?> ">
1587
  </div>
1588
  </div>
1589
 
1590
+ <?php
1591
  }
1592
  }
1593
 
1594
 
1595
  /**
1596
  * Upsell add attachment feature in lite/starter/trial versions.
1597
+ *
1598
  * @param string $editor_id Editor ID
1599
+ *
1600
  * @since 4.6.7
1601
  */
1602
  function ig_es_upsell_add_attachment_feature( $editor_id ) {
1620
 
1621
  /**
1622
  * Upsell pro import features
1623
+ *
1624
  * @since 4.6.7
1625
  */
1626
  function ig_es_upsell_pro_import_features() {
1627
 
1628
  if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1629
  $utm_args = array(
1630
+ 'utm_medium' => 'import_existing_wp_users',
1631
  );
1632
 
1633
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
1645
  </div>
1646
  </label>
1647
  </a>
1648
+ <?php
1649
 
1650
  global $ig_es_tracker;
1651
  $is_woocommerce_active = $ig_es_tracker::is_plugin_activated( 'woocommerce/woocommerce.php' );
1652
  if ( $is_woocommerce_active ) {
1653
+
1654
  $utm_args = array(
1655
+ 'utm_medium' => 'import_from_wc_orders',
1656
  );
1657
 
1658
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
1671
  </div>
1672
  </label>
1673
  </a>
1674
+ <?php
1675
  }
1676
  }
1677
  }
1678
 
1679
  /**
1680
  * Upsell campaign Pro rules
1681
+ *
1682
  * @param array Campaign rules
1683
+ *
1684
  * @return array Campaign rules
1685
+ *
1686
  * @since 4.6.12
1687
  */
1688
  function ig_es_upsell_pro_campaign_rules( $campaign_rules = array() ) {
1689
 
1690
  if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1691
+
1692
  $pro_campaign_rules = array(
1693
+ 'List' => array(
1694
  array(
1695
  'name' => esc_html__( 'is not in List [PRO]', 'email-subscribers' ),
1696
+ 'disabled' => true,
1697
  ),
1698
  ),
1699
  'Subscriber' => array(
1700
+ array(
1701
  'name' => esc_html__( 'Email [PRO]', 'email-subscribers' ),
1702
+ 'disabled' => true,
1703
  ),
1704
+ array(
1705
  'name' => esc_html__( 'Country [PRO]', 'email-subscribers' ),
1706
+ 'disabled' => true,
1707
  ),
1708
  ),
1709
+ 'Campaign' => array(
1710
+ array(
1711
  'name' => esc_html__( 'has received [PRO]', 'email-subscribers' ),
1712
+ 'disabled' => true,
1713
  ),
1714
+ array(
1715
  'name' => esc_html__( 'has not received [PRO]', 'email-subscribers' ),
1716
+ 'disabled' => true,
1717
  ),
1718
+ array(
1719
  'name' => esc_html__( 'has received and opened [PRO]', 'email-subscribers' ),
1720
+ 'disabled' => true,
1721
  ),
1722
+ array(
1723
  'name' => esc_html__( 'has received but not opened [PRO]', 'email-subscribers' ),
1724
+ 'disabled' => true,
1725
  ),
1726
+ array(
1727
  'name' => esc_html__( 'has received and clicked [PRO]', 'email-subscribers' ),
1728
+ 'disabled' => true,
1729
  ),
1730
+ array(
1731
  'name' => esc_html__( 'has received and not clicked [PRO]', 'email-subscribers' ),
1732
+ 'disabled' => true,
1733
  ),
1734
  ),
1735
  );
1744
 
1745
  if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1746
  $utm_args = array(
1747
+ 'utm_medium' => 'broadcast_campaign_rules',
1748
  );
1749
 
1750
  $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
1751
+ $upsell_info = array(
1752
+ 'upgrade_title' => __( 'Send Broadcast to specific audience with PRO', 'email-subscribers' ),
1753
+ 'pricing_url' => $pricing_url,
1754
+ 'upsell_message' => __( 'Now, you can select multiple lists and also filter your subscribers based on their country, emails and whether they have received, opened or clicked a specific campaign or not and then send Broadcast emails to them.', 'email-subscribers' ),
1755
+ 'cta_html' => false,
1756
+ );
1757
 
1758
  ?>
1759
  <div class="block w-2/3 py-2 px-6 mt-2 ">
1764
  }
1765
 
1766
  function ig_es_upsell_contacts_bulk_action( $actions = array() ) {
1767
+
1768
  if ( ES()->can_upsell_features( array( 'lite', 'starter', 'trial' ) ) ) {
1769
  $actions['bulk_send_confirmation_email_upsell'] = __( 'Send confirmation email [PRO]', 'email-subscribers' );
1770
  }
lite/includes/services/class-es-email-delivery-check.php CHANGED
@@ -4,7 +4,7 @@ class ES_Email_Delivery_Check extends ES_Services {
4
 
5
  /**
6
  * Service command
7
- *
8
  * @var string
9
  *
10
  * @sinc 4.6.0
@@ -37,7 +37,7 @@ class ES_Email_Delivery_Check extends ES_Services {
37
 
38
  $res = array();
39
  if ( is_wp_error( $response ) ) {
40
- $res['status'] = 'error';
41
  } else {
42
 
43
  if ( 'success' === $response['status'] && isset( $response['meta']['emailDelivered'] ) && true == $response['meta']['emailDelivered'] ) {
@@ -46,7 +46,6 @@ class ES_Email_Delivery_Check extends ES_Services {
46
  $res['additional_message'] = __( ' The test email did not reach our test server. Did you get any test emails on your email? This could be a temporary problem, but it can also mean that emails are getting stuck on your server, or getting rejected by recipients.', 'email-subscribers' );
47
  $res['status'] = 'error';
48
  }
49
-
50
  }
51
 
52
  return $res;
4
 
5
  /**
6
  * Service command
7
+ *
8
  * @var string
9
  *
10
  * @sinc 4.6.0
37
 
38
  $res = array();
39
  if ( is_wp_error( $response ) ) {
40
+ $res['status'] = 'error';
41
  } else {
42
 
43
  if ( 'success' === $response['status'] && isset( $response['meta']['emailDelivered'] ) && true == $response['meta']['emailDelivered'] ) {
46
  $res['additional_message'] = __( ' The test email did not reach our test server. Did you get any test emails on your email? This could be a temporary problem, but it can also mean that emails are getting stuck on your server, or getting rejected by recipients.', 'email-subscribers' );
47
  $res['status'] = 'error';
48
  }
 
49
  }
50
 
51
  return $res;
lite/includes/services/class-es-service-handle-cron-data.php CHANGED
@@ -4,7 +4,7 @@ class ES_Service_Handle_Cron_Data extends ES_Services {
4
 
5
  /**
6
  * Service command
7
- *
8
  * @var string
9
  *
10
  * @sinc 4.6.1
@@ -22,13 +22,13 @@ class ES_Service_Handle_Cron_Data extends ES_Services {
22
 
23
  /**
24
  * Trigger cron save data
25
- *
26
  * @since 4.6.1
27
  */
28
  public function handle_es_cron_data( $options = array() ) {
29
 
30
  if ( ES()->validate_service_request( array( 'es_cron' ) ) ) {
31
-
32
  $ig_es_set_cron_data = get_option( 'ig_es_set_cron_data', 'no' );
33
  $ig_es_set_cron_data = ( ! empty( $options ) && 'email_subscribers_settings' === $options['option_page'] ) ? 'no' : $ig_es_set_cron_data;
34
  if ( 'yes' === $ig_es_set_cron_data ) {
@@ -46,28 +46,27 @@ class ES_Service_Handle_Cron_Data extends ES_Services {
46
  update_option( 'ig_es_set_cron_data', 'yes' );
47
  delete_option( 'ig_es_cron_data_deleted' );
48
  } else {
49
-
50
  if ( ES()->is_trial() ) {
51
  $ig_es_cron_data_deleted = get_option( 'ig_es_cron_data_deleted', 'no' );
52
-
53
  // Check if we have already deleted the cron data.
54
  if ( 'yes' === $ig_es_cron_data_deleted ) {
55
  return;
56
  }
57
-
58
  $request_response = $this->delete_cron_data();
59
-
60
  if ( ! $request_response instanceof WP_Error && ! empty( $request_response['status'] ) && 'SUCCESS' === $request_response['status'] ) {
61
  update_option( 'ig_es_cron_data_deleted', 'yes' );
62
  }
63
  }
64
-
65
  }
66
  }
67
 
68
  /**
69
  * Delete cron data.
70
- *
71
  * @since 4.6.1
72
  */
73
  public function delete_cron_data() {
@@ -84,7 +83,7 @@ class ES_Service_Handle_Cron_Data extends ES_Services {
84
  * Send cron data to our server
85
  *
86
  * @param array $data
87
- *
88
  * @return array
89
  *
90
  * @since 4.6.1
@@ -94,16 +93,16 @@ class ES_Service_Handle_Cron_Data extends ES_Services {
94
  $response = array(
95
  'status' => 'error',
96
  );
97
-
98
  if ( ! empty( $data ) ) {
99
  $data['tasks'][] = 'store-cron';
100
  $options = array(
101
- 'timeout' => 15,
102
- 'method' => 'POST',
103
- 'body' => $data,
104
- 'sslverify' => false
105
  );
106
- $response = $this->send_request( $options );
107
  }
108
 
109
  return $response;
4
 
5
  /**
6
  * Service command
7
+ *
8
  * @var string
9
  *
10
  * @sinc 4.6.1
22
 
23
  /**
24
  * Trigger cron save data
25
+ *
26
  * @since 4.6.1
27
  */
28
  public function handle_es_cron_data( $options = array() ) {
29
 
30
  if ( ES()->validate_service_request( array( 'es_cron' ) ) ) {
31
+
32
  $ig_es_set_cron_data = get_option( 'ig_es_set_cron_data', 'no' );
33
  $ig_es_set_cron_data = ( ! empty( $options ) && 'email_subscribers_settings' === $options['option_page'] ) ? 'no' : $ig_es_set_cron_data;
34
  if ( 'yes' === $ig_es_set_cron_data ) {
46
  update_option( 'ig_es_set_cron_data', 'yes' );
47
  delete_option( 'ig_es_cron_data_deleted' );
48
  } else {
49
+
50
  if ( ES()->is_trial() ) {
51
  $ig_es_cron_data_deleted = get_option( 'ig_es_cron_data_deleted', 'no' );
52
+
53
  // Check if we have already deleted the cron data.
54
  if ( 'yes' === $ig_es_cron_data_deleted ) {
55
  return;
56
  }
57
+
58
  $request_response = $this->delete_cron_data();
59
+
60
  if ( ! $request_response instanceof WP_Error && ! empty( $request_response['status'] ) && 'SUCCESS' === $request_response['status'] ) {
61
  update_option( 'ig_es_cron_data_deleted', 'yes' );
62
  }
63
  }
 
64
  }
65
  }
66
 
67
  /**
68
  * Delete cron data.
69
+ *
70
  * @since 4.6.1
71
  */
72
  public function delete_cron_data() {
83
  * Send cron data to our server
84
  *
85
  * @param array $data
86
+ *
87
  * @return array
88
  *
89
  * @since 4.6.1
93
  $response = array(
94
  'status' => 'error',
95
  );
96
+
97
  if ( ! empty( $data ) ) {
98
  $data['tasks'][] = 'store-cron';
99
  $options = array(
100
+ 'timeout' => 15,
101
+ 'method' => 'POST',
102
+ 'body' => $data,
103
+ 'sslverify' => false,
104
  );
105
+ $response = $this->send_request( $options );
106
  }
107
 
108
  return $response;
lite/includes/services/class-es-service-process-email-content.php CHANGED
@@ -4,7 +4,7 @@ class ES_Service_Process_Email_Content extends ES_Services {
4
 
5
  /**
6
  * Service command
7
- *
8
  * @var string
9
  *
10
  * @sinc 4.6.1
@@ -24,7 +24,7 @@ class ES_Service_Process_Email_Content extends ES_Services {
24
  * Get inline CSS
25
  *
26
  * @param array $data
27
- *
28
  * @return array
29
  *
30
  * @since 4.6.1
@@ -32,22 +32,22 @@ class ES_Service_Process_Email_Content extends ES_Services {
32
  public function process_email_content( $data = array() ) {
33
 
34
  $data = apply_filters( 'ig_es_util_data', $data );
35
-
36
  // Check if we have content to process and task to be performed.
37
  if ( ! empty( $data['content'] ) && ! empty( $data['tasks'] ) ) {
38
  $options = array(
39
  'timeout' => 15,
40
  'method' => 'POST',
41
- 'body' => $data
42
  );
43
  $response = $this->send_request( $options );
44
-
45
  // Change data only if we have got a valid response from the service.
46
  if ( ! $response instanceof WP_Error ) {
47
  $data = $response;
48
  }
49
  }
50
-
51
  return $data;
52
  }
53
  }
4
 
5
  /**
6
  * Service command
7
+ *
8
  * @var string
9
  *
10
  * @sinc 4.6.1
24
  * Get inline CSS
25
  *
26
  * @param array $data
27
+ *
28
  * @return array
29
  *
30
  * @since 4.6.1
32
  public function process_email_content( $data = array() ) {
33
 
34
  $data = apply_filters( 'ig_es_util_data', $data );
35
+
36
  // Check if we have content to process and task to be performed.
37
  if ( ! empty( $data['content'] ) && ! empty( $data['tasks'] ) ) {
38
  $options = array(
39
  'timeout' => 15,
40
  'method' => 'POST',
41
+ 'body' => $data,
42
  );
43
  $response = $this->send_request( $options );
44
+
45
  // Change data only if we have got a valid response from the service.
46
  if ( ! $response instanceof WP_Error ) {
47
  $data = $response;
48
  }
49
  }
50
+
51
  return $data;
52
  }
53
  }
lite/includes/services/class-es-service-spam-score-check.php CHANGED
@@ -4,7 +4,7 @@ class ES_Service_Spam_Score_Check extends ES_Services {
4
 
5
  /**
6
  * Service command
7
- *
8
  * @var string
9
  *
10
  * @since 4.6.1
@@ -24,7 +24,7 @@ class ES_Service_Spam_Score_Check extends ES_Services {
24
  * Get spam score data
25
  *
26
  * @param array $data
27
- *
28
  * @return array
29
  *
30
  * @since 4.6.1
@@ -37,11 +37,11 @@ class ES_Service_Spam_Score_Check extends ES_Services {
37
 
38
  if ( ES()->validate_service_request( array( 'spam_score_check' ) ) ) {
39
  if ( ! empty( $data ) ) {
40
- $data['options'] = 'full';
41
- $options = array(
42
  'timeout' => 50,
43
  'method' => 'POST',
44
- 'body' => $data
45
  );
46
  $response_data = $this->send_request( $options );
47
  $response['data'] = $response_data;
4
 
5
  /**
6
  * Service command
7
+ *
8
  * @var string
9
  *
10
  * @since 4.6.1
24
  * Get spam score data
25
  *
26
  * @param array $data
27
+ *
28
  * @return array
29
  *
30
  * @since 4.6.1
37
 
38
  if ( ES()->validate_service_request( array( 'spam_score_check' ) ) ) {
39
  if ( ! empty( $data ) ) {
40
+ $data['options'] = 'full';
41
+ $options = array(
42
  'timeout' => 50,
43
  'method' => 'POST',
44
+ 'body' => $data,
45
  );
46
  $response_data = $this->send_request( $options );
47
  $response['data'] = $response_data;
lite/includes/services/class-es-services.php CHANGED
@@ -1,19 +1,18 @@
1
  <?php
2
 
3
  class ES_Services {
4
-
5
  /**
6
  * API URL
7
- *
8
  * @since 4.6.0
9
  * @var string
10
- *
11
  */
12
  public $api_url = 'https://api.icegram.com';
13
 
14
  /**
15
  * Service command
16
- *
17
  * @var string
18
  *
19
  * @sinc 4.6.0
@@ -32,20 +31,19 @@ class ES_Services {
32
  /**
33
  * Send Request
34
  *
35
- * @param array $options
36
  * @param string $method
37
  *
38
  * @since 4.6.0
39
  */
40
  public function send_request( $options = array(), $method = 'POST' ) {
41
 
42
-
43
  $response = array();
44
-
45
  if ( empty( $this->cmd ) ) {
46
  return new WP_Error( '404', 'Command Not Found' );
47
  }
48
-
49
  // Request is valid if trial is valid or user is on a premium plan.
50
  $is_request_valid = ES()->is_trial_valid() || ES()->is_premium();
51
 
@@ -56,9 +54,9 @@ class ES_Services {
56
  if ( ! $is_request_valid ) {
57
  return $options;
58
  }
59
-
60
  $url = $this->api_url . $this->cmd;
61
-
62
  $options = apply_filters( 'ig_es_service_request_data', $options );
63
 
64
  if ( ! empty( $options ) && is_array( $options ) ) {
@@ -67,23 +65,22 @@ class ES_Services {
67
  } else {
68
  $response = wp_remote_get( $url, $options );
69
  }
70
-
71
  if ( ! is_wp_error( $response ) ) {
72
-
73
  if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
74
-
75
  $response_data = $response['body'];
76
-
77
  if ( 'error' != $response_data ) {
78
 
79
  $response_data = json_decode( $response_data, true );
80
-
81
  do_action( 'ig_es_service_response_received', $response_data, $options );
82
 
83
  return $response_data;
84
  }
85
  }
86
-
87
  }
88
  }
89
 
1
  <?php
2
 
3
  class ES_Services {
4
+
5
  /**
6
  * API URL
7
+ *
8
  * @since 4.6.0
9
  * @var string
 
10
  */
11
  public $api_url = 'https://api.icegram.com';
12
 
13
  /**
14
  * Service command
15
+ *
16
  * @var string
17
  *
18
  * @sinc 4.6.0
31
  /**
32
  * Send Request
33
  *
34
+ * @param array $options
35
  * @param string $method
36
  *
37
  * @since 4.6.0
38
  */
39
  public function send_request( $options = array(), $method = 'POST' ) {
40
 
 
41
  $response = array();
42
+
43
  if ( empty( $this->cmd ) ) {
44
  return new WP_Error( '404', 'Command Not Found' );
45
  }
46
+
47
  // Request is valid if trial is valid or user is on a premium plan.
48
  $is_request_valid = ES()->is_trial_valid() || ES()->is_premium();
49
 
54
  if ( ! $is_request_valid ) {
55
  return $options;
56
  }
57
+
58
  $url = $this->api_url . $this->cmd;
59
+
60
  $options = apply_filters( 'ig_es_service_request_data', $options );
61
 
62
  if ( ! empty( $options ) && is_array( $options ) ) {
65
  } else {
66
  $response = wp_remote_get( $url, $options );
67
  }
68
+
69
  if ( ! is_wp_error( $response ) ) {
70
+
71
  if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
72
+
73
  $response_data = $response['body'];
74
+
75
  if ( 'error' != $response_data ) {
76
 
77
  $response_data = json_decode( $response_data, true );
78
+
79
  do_action( 'ig_es_service_response_received', $response_data, $options );
80
 
81
  return $response_data;
82
  }
83
  }
 
84
  }
85
  }
86
 
lite/includes/upgrade/es-update-functions.php CHANGED
@@ -41,17 +41,20 @@ function ig_es_update_327_change_email_type() {
41
  // Compose table
42
  $template_table_exists = $wpdb->query( "SHOW TABLES LIKE '{$wpdb->prefix}es_templatetable'" );
43
  if ( $template_table_exists > 0 ) {
44
- $wpdb->query( "UPDATE {$wpdb->prefix}es_templatetable
 
45
  SET es_email_type =
46
  ( CASE
47
  WHEN es_email_type = 'Static Template' THEN 'Newsletter'
48
  WHEN es_email_type = 'Dynamic Template' THEN 'Post Notification'
49
  ELSE es_email_type
50
- END ) " );
 
51
  }
52
 
53
  // Sent Details table
54
- $wpdb->query( "UPDATE {$wpdb->prefix}es_sentdetails
 
55
  SET es_sent_type =
56
  ( CASE
57
  WHEN es_sent_type = 'Instant Mail' THEN 'Immediately'
@@ -63,17 +66,19 @@ function ig_es_update_327_change_email_type() {
63
  WHEN es_sent_source = 'manual' THEN 'Newsletter'
64
  WHEN es_sent_source = 'notification' THEN 'Post Notification'
65
  ELSE es_sent_source
66
- END ) " );
 
67
 
68
  // Delivery Reports table
69
- $wpdb->query( "UPDATE {$wpdb->prefix}es_deliverreport
 
70
  SET es_deliver_senttype =
71
  ( CASE
72
  WHEN es_deliver_senttype = 'Instant Mail' THEN 'Immediately'
73
  WHEN es_deliver_senttype = 'Cron Mail' THEN 'Cron'
74
  ELSE es_deliver_senttype
75
- END ) " );
76
-
77
 
78
  }
79
 
@@ -132,7 +137,6 @@ function ig_es_update_330_import_options() {
132
  update_option( $new_option_name, $option_value );
133
  delete_option( $old_option_name );
134
  }
135
-
136
  }
137
 
138
  // Do not pull data for new users as there is no pluginconfig table created on activation
@@ -152,7 +156,7 @@ function ig_es_update_330_import_options() {
152
  }
153
  }
154
 
155
- //Update User Roles Settings
156
  $es_c_rolesandcapabilities = get_option( 'ig_es_rolesandcapabilities', 'norecord' );
157
 
158
  if ( 'norecord' != $es_c_rolesandcapabilities ) {
@@ -186,15 +190,17 @@ function ig_es_update_336_add_template_slug() {
186
  if ( $template_table_exists > 0 ) {
187
 
188
  // To check if column es_templ_slug exists or not
189
- $results_template_col = $wpdb->get_results( $wpdb->prepare( "SHOW COLUMNS FROM {$wpdb->prefix}es_templatetable LIKE %s", 'es_templ_slug' ) , 'ARRAY_A' );
190
  $template_num_rows = $wpdb->num_rows;
191
 
192
  // If column doesn't exists, then insert it
193
  if ( '1' != $template_num_rows ) {
194
  // Template table
195
- $wpdb->query( "ALTER TABLE {$wpdb->prefix}es_templatetable
 
196
  ADD COLUMN es_templ_slug VARCHAR(255) NULL
197
- AFTER es_email_type" );
 
198
  }
199
  }
200
  }
@@ -223,14 +229,14 @@ function ig_es_update_340_migrate_templates_to_cpt() {
223
  return;
224
  }
225
 
226
- $arrRes = $wpdb->get_results(
227
- "SELECT es_tt.*,
228
  IFNULL(es_not.es_note_id, '') as es_note_id
229
  FROM {$wpdb->prefix}es_templatetable AS es_tt
230
  LEFT JOIN {$wpdb->prefix}es_notification AS es_not
231
  ON(es_not.es_note_templ = es_tt.es_templ_id)",
232
- ARRAY_A
233
- );
234
 
235
  if ( ! empty( $arrRes ) ) {
236
 
@@ -244,8 +250,8 @@ function ig_es_update_340_migrate_templates_to_cpt() {
244
  'post_status' => 'publish',
245
  'post_type' => 'es_template',
246
  'meta_input' => array(
247
- 'es_template_type' => $tmpl['es_email_type']
248
- )
249
  );
250
  // Insert the post into the database
251
  $last_inserted_id = wp_insert_post( $es_post );
@@ -260,7 +266,6 @@ function ig_es_update_340_migrate_templates_to_cpt() {
260
  $sSql = "UPDATE {$wpdb->prefix}es_notification SET es_note_templ = (CASE " . implode( ' ', $es_note_ids ) . ' END)';
261
  $wpbd->query( $sSql );
262
  }
263
-
264
  }
265
 
266
  update_option( 'es_template_migration_done', 'yes' );
@@ -370,7 +375,6 @@ function ig_es_update_340_migrate_keywords() {
370
  function ig_es_update_340_db_version() {
371
  ES_Install::update_db_version( '3.4.0' );
372
 
373
-
374
  }
375
 
376
  /* --------------------- ES 3.4.0 (End)--------------------------- */
@@ -392,8 +396,7 @@ function ig_es_update_3516_create_subscribers_ips_table() {
392
  KEY ip (ip)
393
  ) $charset_collate";
394
 
395
-
396
- require_once ABSPATH . 'wp-admin/includes/upgrade.php' ;
397
  dbDelta( $es_subscriber_ips_table );
398
  }
399
 
@@ -411,7 +414,7 @@ function ig_es_update_400_delete_tables() {
411
  $tables_to_delete = array(
412
  $wpdb->prefix . 'ig_blocked_emails',
413
  $wpdb->prefix . 'ig_campaigns',
414
- //$wpdb->prefix . 'ig_contacts',
415
  $wpdb->prefix . 'ig_contacts_ips',
416
  $wpdb->prefix . 'ig_forms',
417
  $wpdb->prefix . 'ig_lists',
@@ -500,9 +503,8 @@ function ig_es_update_400_migrate_reports_data() {
500
  * - Migrate individual notification data from es_deliverreport to ig_es_sending_queue table
501
  * es_deliverreport => ig_es_sending_queue
502
  */
503
- //@ini_set( 'max_execution_time', 0 );
504
- //ES_DB_Sending_Queue::migrate_reports_data();
505
-
506
  }
507
 
508
  function ig_es_update_400_migrate_group_selectors_forms() {
@@ -667,7 +669,7 @@ function ig_es_update_4113_migrate_categories_in_campaigns_table() {
667
  if ( ! empty( $campaign_category_map ) ) {
668
  foreach ( $campaign_category_map as $value ) {
669
  $categories_str = ES_Common::prepare_categories_migration_string( $value['categories'] );
670
- //remove category with 0
671
  $categories_str = str_replace( '##0', '', $categories_str );
672
  $categories[] = " WHEN categories = '" . esc_sql( $value['categories'] ) . "' THEN '" . $categories_str . "'";
673
  }
@@ -722,7 +724,7 @@ function ig_es_update_4115_migrate_db_update_history() {
722
  '4.0.15' => '4015_db_updated_at',
723
  '4.1.1' => '411_db_updated_at',
724
  '4.1.7' => '417_db_updated_at',
725
- '4.1.13' => '4113_db_updated_at'
726
  );
727
 
728
  foreach ( $db_update_at_options as $version => $option ) {
@@ -769,7 +771,6 @@ function ig_es_update_4115_db_version() {
769
  function ig_es_update_420_alter_campaigns_table() {
770
  global $wpdb;
771
 
772
-
773
  $wpdb->hide_errors();
774
 
775
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_campaigns" );
@@ -818,7 +819,7 @@ function ig_es_update_420_migrate_mailer_options() {
818
  $es_email_type = get_option( 'ig_es_email_type' );
819
  $default_mailer = ( 'php_html_mail' === $es_email_type || 'php_plaintext_mail' === $es_email_type ) ? 'phpmail' : 'wpmail';
820
  $ig_es_mailer_settings['mailer'] = $default_mailer;
821
- //smtp settings default option
822
  $enable_smtp = get_option( 'ig_es_enable_smtp', 'no' );
823
  $ig_es_mailer_settings['mailer'] = ( 'yes' === $enable_smtp ) ? 'smtp' : $default_mailer;
824
  $smtp_host = get_option( 'ig_es_smtp_host', '' );
@@ -1013,7 +1014,7 @@ function ig_es_update_431_delete_options() {
1013
 
1014
  $options_str = "'" . implode( "','", $options_to_delete ) . "'";
1015
 
1016
- $wpbd->query(
1017
  "DELETE FROM {$wpbd->prefix}options WHERE option_name IN($options_str, %s)"
1018
  );
1019
  }
@@ -1129,7 +1130,7 @@ function ig_es_update_442_set_workflows_default_permission() {
1129
  update_option( 'ig_es_user_roles', ES_Install::get_default_permissions() );
1130
  } elseif ( ! empty( $user_role_permissions ) && is_array( $user_role_permissions ) ) {
1131
  $user_role_permissions['workflows'] = array(
1132
- 'administrator' => 'yes'
1133
  );
1134
  update_option( 'ig_es_user_roles', $user_role_permissions );
1135
  }
@@ -1191,11 +1192,11 @@ function ig_es_update_4410_db_version() {
1191
  /* --------------------- ES 4.5.0(Start)--------------------------- */
1192
  function ig_es_update_450_alter_actions_table() {
1193
  global $wpdb;
1194
-
1195
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_actions" );
1196
 
1197
  if ( ! in_array( 'ip', $cols ) ) {
1198
- $wpdb->query(
1199
  "ALTER TABLE {$wpdb->prefix}ig_actions
1200
  ADD COLUMN ip varchar(50) NULL AFTER `list_id`,
1201
  ADD COLUMN country varchar(50) NULL AFTER `ip`,
@@ -1220,7 +1221,7 @@ function ig_es_update_450_db_version() {
1220
  /* --------------------- ES 4.5.7(Start)--------------------------- */
1221
  function ig_es_update_457_alter_list_table() {
1222
  global $wpdb;
1223
-
1224
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_lists" );
1225
 
1226
  if ( ! in_array( 'hash', $cols, true ) ) {
@@ -1238,7 +1239,7 @@ function ig_es_update_457_alter_list_table() {
1238
  */
1239
  function ig_es_update_457_add_list_hash() {
1240
  global $wpdb;
1241
-
1242
  $lists = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}ig_lists", ARRAY_A );
1243
 
1244
  if ( ! empty( $lists ) ) {
@@ -1273,7 +1274,7 @@ function ig_es_update_457_db_version() {
1273
  */
1274
  function ig_es_update_463_alter_contacts_table() {
1275
  global $wpdb;
1276
-
1277
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_contacts" );
1278
 
1279
  if ( ! in_array( 'ip_address', $cols, true ) ) {
@@ -1354,7 +1355,7 @@ function ig_es_update_466_db_version() {
1354
  */
1355
  function ig_es_update_467_alter_contacts_table() {
1356
  global $wpdb;
1357
-
1358
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_contacts" );
1359
 
1360
  if ( ! in_array( 'country_code', $cols, true ) ) {
@@ -1415,7 +1416,7 @@ function ig_es_update_468_db_version() {
1415
  */
1416
  function ig_es_update_469_alter_wc_guests_table() {
1417
  global $wpdb;
1418
-
1419
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_wc_guests" );
1420
 
1421
  if ( ! in_array( 'meta', $cols, true ) ) {
@@ -1445,10 +1446,10 @@ function ig_es_update_469_db_version() {
1445
  * @since 4.6.13
1446
  */
1447
  function ig_es_migrate_4613_sequence_list_settings_into_campaign_rules() {
1448
-
1449
  $args = array(
1450
  'include_types' => array(
1451
- 'sequence_message'
1452
  ),
1453
  );
1454
 
@@ -1461,7 +1462,7 @@ function ig_es_migrate_4613_sequence_list_settings_into_campaign_rules() {
1461
  $list_ids = explode( ',', $list_ids );
1462
  $campaign_meta = ! empty( $campaign['meta'] ) ? maybe_unserialize( $campaign['meta'] ) : array();
1463
  if ( empty( $campaign_meta['list_conditions'] ) ) {
1464
- $list_conditions = array();
1465
  $list_conditions_data = array(
1466
  'field' => '_lists__in',
1467
  'operator' => 'is',
@@ -1470,7 +1471,7 @@ function ig_es_migrate_4613_sequence_list_settings_into_campaign_rules() {
1470
  foreach ( $list_ids as $index => $list_id ) {
1471
  $list_conditions_data['value'][] = $list_id;
1472
  }
1473
- $list_conditions[][] = $list_conditions_data;
1474
  $campaign_meta['list_conditions'] = $list_conditions;
1475
  ES()->campaigns_db->update_campaign_meta( $campaign_id, $campaign_meta );
1476
  }
@@ -1497,7 +1498,7 @@ function ig_es_update_4613_db_version() {
1497
  *
1498
  * We are adding index to improve the response time of the select query
1499
  * e.g. Imrpoves performance of select query in ES_DB_Sending_Queue::do_insert_from_contacts_table() to get contact ids
1500
- *
1501
  * @since 4.7.8
1502
  */
1503
  function ig_es_add_index_to_list_contacts_table() {
@@ -1506,8 +1507,10 @@ function ig_es_add_index_to_list_contacts_table() {
1506
  $index_exists = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->prefix}ig_lists_contacts WHERE column_name = 'contact_id' AND key_name = 'contact_id'" );
1507
 
1508
  if ( is_null( $index_exists ) ) {
1509
- $wpdb->query( "ALTER TABLE {$wpdb->prefix}ig_lists_contacts
1510
- ADD INDEX contact_id( contact_id );" );
 
 
1511
  }
1512
  }
1513
 
@@ -1529,7 +1532,7 @@ function ig_es_update_478_db_version() {
1529
  *
1530
  * On some web hosts which uses db optimization services like Percona,
1531
  * we can't insert data into a table which don't have primay key column
1532
- *
1533
  * @since 4.7.9
1534
  */
1535
  function ig_es_add_primay_key_to_actions_table() {
@@ -1538,7 +1541,7 @@ function ig_es_add_primay_key_to_actions_table() {
1538
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_actions" );
1539
 
1540
  if ( ! in_array( 'id', $cols, true ) ) {
1541
- $wpdb->query(
1542
  "ALTER TABLE {$wpdb->prefix}ig_actions
1543
  ADD COLUMN id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;"
1544
  );
41
  // Compose table
42
  $template_table_exists = $wpdb->query( "SHOW TABLES LIKE '{$wpdb->prefix}es_templatetable'" );
43
  if ( $template_table_exists > 0 ) {
44
+ $wpdb->query(
45
+ "UPDATE {$wpdb->prefix}es_templatetable
46
  SET es_email_type =
47
  ( CASE
48
  WHEN es_email_type = 'Static Template' THEN 'Newsletter'
49
  WHEN es_email_type = 'Dynamic Template' THEN 'Post Notification'
50
  ELSE es_email_type
51
+ END ) "
52
+ );
53
  }
54
 
55
  // Sent Details table
56
+ $wpdb->query(
57
+ "UPDATE {$wpdb->prefix}es_sentdetails
58
  SET es_sent_type =
59
  ( CASE
60
  WHEN es_sent_type = 'Instant Mail' THEN 'Immediately'
66
  WHEN es_sent_source = 'manual' THEN 'Newsletter'
67
  WHEN es_sent_source = 'notification' THEN 'Post Notification'
68
  ELSE es_sent_source
69
+ END ) "
70
+ );
71
 
72
  // Delivery Reports table
73
+ $wpdb->query(
74
+ "UPDATE {$wpdb->prefix}es_deliverreport
75
  SET es_deliver_senttype =
76
  ( CASE
77
  WHEN es_deliver_senttype = 'Instant Mail' THEN 'Immediately'
78
  WHEN es_deliver_senttype = 'Cron Mail' THEN 'Cron'
79
  ELSE es_deliver_senttype
80
+ END ) "
81
+ );
82
 
83
  }
84
 
137
  update_option( $new_option_name, $option_value );
138
  delete_option( $old_option_name );
139
  }
 
140
  }
141
 
142
  // Do not pull data for new users as there is no pluginconfig table created on activation
156
  }
157
  }
158
 
159
+ // Update User Roles Settings
160
  $es_c_rolesandcapabilities = get_option( 'ig_es_rolesandcapabilities', 'norecord' );
161
 
162
  if ( 'norecord' != $es_c_rolesandcapabilities ) {
190
  if ( $template_table_exists > 0 ) {
191
 
192
  // To check if column es_templ_slug exists or not
193
+ $results_template_col = $wpdb->get_results( $wpdb->prepare( "SHOW COLUMNS FROM {$wpdb->prefix}es_templatetable LIKE %s", 'es_templ_slug' ), 'ARRAY_A' );
194
  $template_num_rows = $wpdb->num_rows;
195
 
196
  // If column doesn't exists, then insert it
197
  if ( '1' != $template_num_rows ) {
198
  // Template table
199
+ $wpdb->query(
200
+ "ALTER TABLE {$wpdb->prefix}es_templatetable
201
  ADD COLUMN es_templ_slug VARCHAR(255) NULL
202
+ AFTER es_email_type"
203
+ );
204
  }
205
  }
206
  }
229
  return;
230
  }
231
 
232
+ $arrRes = $wpdb->get_results(
233
+ "SELECT es_tt.*,
234
  IFNULL(es_not.es_note_id, '') as es_note_id
235
  FROM {$wpdb->prefix}es_templatetable AS es_tt
236
  LEFT JOIN {$wpdb->prefix}es_notification AS es_not
237
  ON(es_not.es_note_templ = es_tt.es_templ_id)",
238
+ ARRAY_A
239
+ );
240
 
241
  if ( ! empty( $arrRes ) ) {
242
 
250
  'post_status' => 'publish',
251
  'post_type' => 'es_template',
252
  'meta_input' => array(
253
+ 'es_template_type' => $tmpl['es_email_type'],
254
+ ),
255
  );
256
  // Insert the post into the database
257
  $last_inserted_id = wp_insert_post( $es_post );
266
  $sSql = "UPDATE {$wpdb->prefix}es_notification SET es_note_templ = (CASE " . implode( ' ', $es_note_ids ) . ' END)';
267
  $wpbd->query( $sSql );
268
  }
 
269
  }
270
 
271
  update_option( 'es_template_migration_done', 'yes' );
375
  function ig_es_update_340_db_version() {
376
  ES_Install::update_db_version( '3.4.0' );
377
 
 
378
  }
379
 
380
  /* --------------------- ES 3.4.0 (End)--------------------------- */
396
  KEY ip (ip)
397
  ) $charset_collate";
398
 
399
+ require_once ABSPATH . 'wp-admin/includes/upgrade.php';
 
400
  dbDelta( $es_subscriber_ips_table );
401
  }
402
 
414
  $tables_to_delete = array(
415
  $wpdb->prefix . 'ig_blocked_emails',
416
  $wpdb->prefix . 'ig_campaigns',
417
+ // $wpdb->prefix . 'ig_contacts',
418
  $wpdb->prefix . 'ig_contacts_ips',
419
  $wpdb->prefix . 'ig_forms',
420
  $wpdb->prefix . 'ig_lists',
503
  * - Migrate individual notification data from es_deliverreport to ig_es_sending_queue table
504
  * es_deliverreport => ig_es_sending_queue
505
  */
506
+ // @ini_set( 'max_execution_time', 0 );
507
+ // ES_DB_Sending_Queue::migrate_reports_data();
 
508
  }
509
 
510
  function ig_es_update_400_migrate_group_selectors_forms() {
669
  if ( ! empty( $campaign_category_map ) ) {
670
  foreach ( $campaign_category_map as $value ) {
671
  $categories_str = ES_Common::prepare_categories_migration_string( $value['categories'] );
672
+ // remove category with 0
673
  $categories_str = str_replace( '##0', '', $categories_str );
674
  $categories[] = " WHEN categories = '" . esc_sql( $value['categories'] ) . "' THEN '" . $categories_str . "'";
675
  }
724
  '4.0.15' => '4015_db_updated_at',
725
  '4.1.1' => '411_db_updated_at',
726
  '4.1.7' => '417_db_updated_at',
727
+ '4.1.13' => '4113_db_updated_at',
728
  );
729
 
730
  foreach ( $db_update_at_options as $version => $option ) {
771
  function ig_es_update_420_alter_campaigns_table() {
772
  global $wpdb;
773
 
 
774
  $wpdb->hide_errors();
775
 
776
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_campaigns" );
819
  $es_email_type = get_option( 'ig_es_email_type' );
820
  $default_mailer = ( 'php_html_mail' === $es_email_type || 'php_plaintext_mail' === $es_email_type ) ? 'phpmail' : 'wpmail';
821
  $ig_es_mailer_settings['mailer'] = $default_mailer;
822
+ // smtp settings default option
823
  $enable_smtp = get_option( 'ig_es_enable_smtp', 'no' );
824
  $ig_es_mailer_settings['mailer'] = ( 'yes' === $enable_smtp ) ? 'smtp' : $default_mailer;
825
  $smtp_host = get_option( 'ig_es_smtp_host', '' );
1014
 
1015
  $options_str = "'" . implode( "','", $options_to_delete ) . "'";
1016
 
1017
+ $wpbd->query(
1018
  "DELETE FROM {$wpbd->prefix}options WHERE option_name IN($options_str, %s)"
1019
  );
1020
  }
1130
  update_option( 'ig_es_user_roles', ES_Install::get_default_permissions() );
1131
  } elseif ( ! empty( $user_role_permissions ) && is_array( $user_role_permissions ) ) {
1132
  $user_role_permissions['workflows'] = array(
1133
+ 'administrator' => 'yes',
1134
  );
1135
  update_option( 'ig_es_user_roles', $user_role_permissions );
1136
  }
1192
  /* --------------------- ES 4.5.0(Start)--------------------------- */
1193
  function ig_es_update_450_alter_actions_table() {
1194
  global $wpdb;
1195
+
1196
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_actions" );
1197
 
1198
  if ( ! in_array( 'ip', $cols ) ) {
1199
+ $wpdb->query(
1200
  "ALTER TABLE {$wpdb->prefix}ig_actions
1201
  ADD COLUMN ip varchar(50) NULL AFTER `list_id`,
1202
  ADD COLUMN country varchar(50) NULL AFTER `ip`,
1221
  /* --------------------- ES 4.5.7(Start)--------------------------- */
1222
  function ig_es_update_457_alter_list_table() {
1223
  global $wpdb;
1224
+
1225
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_lists" );
1226
 
1227
  if ( ! in_array( 'hash', $cols, true ) ) {
1239
  */
1240
  function ig_es_update_457_add_list_hash() {
1241
  global $wpdb;
1242
+
1243
  $lists = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}ig_lists", ARRAY_A );
1244
 
1245
  if ( ! empty( $lists ) ) {
1274
  */
1275
  function ig_es_update_463_alter_contacts_table() {
1276
  global $wpdb;
1277
+
1278
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_contacts" );
1279
 
1280
  if ( ! in_array( 'ip_address', $cols, true ) ) {
1355
  */
1356
  function ig_es_update_467_alter_contacts_table() {
1357
  global $wpdb;
1358
+
1359
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_contacts" );
1360
 
1361
  if ( ! in_array( 'country_code', $cols, true ) ) {
1416
  */
1417
  function ig_es_update_469_alter_wc_guests_table() {
1418
  global $wpdb;
1419
+
1420
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_wc_guests" );
1421
 
1422
  if ( ! in_array( 'meta', $cols, true ) ) {
1446
  * @since 4.6.13
1447
  */
1448
  function ig_es_migrate_4613_sequence_list_settings_into_campaign_rules() {
1449
+
1450
  $args = array(
1451
  'include_types' => array(
1452
+ 'sequence_message',
1453
  ),
1454
  );
1455
 
1462
  $list_ids = explode( ',', $list_ids );
1463
  $campaign_meta = ! empty( $campaign['meta'] ) ? maybe_unserialize( $campaign['meta'] ) : array();
1464
  if ( empty( $campaign_meta['list_conditions'] ) ) {
1465
+ $list_conditions = array();
1466
  $list_conditions_data = array(
1467
  'field' => '_lists__in',
1468
  'operator' => 'is',
1471
  foreach ( $list_ids as $index => $list_id ) {
1472
  $list_conditions_data['value'][] = $list_id;
1473
  }
1474
+ $list_conditions[][] = $list_conditions_data;
1475
  $campaign_meta['list_conditions'] = $list_conditions;
1476
  ES()->campaigns_db->update_campaign_meta( $campaign_id, $campaign_meta );
1477
  }
1498
  *
1499
  * We are adding index to improve the response time of the select query
1500
  * e.g. Imrpoves performance of select query in ES_DB_Sending_Queue::do_insert_from_contacts_table() to get contact ids
1501
+ *
1502
  * @since 4.7.8
1503
  */
1504
  function ig_es_add_index_to_list_contacts_table() {
1507
  $index_exists = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->prefix}ig_lists_contacts WHERE column_name = 'contact_id' AND key_name = 'contact_id'" );
1508
 
1509
  if ( is_null( $index_exists ) ) {
1510
+ $wpdb->query(
1511
+ "ALTER TABLE {$wpdb->prefix}ig_lists_contacts
1512
+ ADD INDEX contact_id( contact_id );"
1513
+ );
1514
  }
1515
  }
1516
 
1532
  *
1533
  * On some web hosts which uses db optimization services like Percona,
1534
  * we can't insert data into a table which don't have primay key column
1535
+ *
1536
  * @since 4.7.9
1537
  */
1538
  function ig_es_add_primay_key_to_actions_table() {
1541
  $cols = $wpdb->get_col( "SHOW COLUMNS FROM {$wpdb->prefix}ig_actions" );
1542
 
1543
  if ( ! in_array( 'id', $cols, true ) ) {
1544
+ $wpdb->query(
1545
  "ALTER TABLE {$wpdb->prefix}ig_actions
1546
  ADD COLUMN id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;"
1547
  );
lite/includes/workflows/abstracts/class-es-workflow-action.php CHANGED
@@ -80,7 +80,7 @@ abstract class ES_Workflow_Action {
80
  * This prop may not be set depending on the context.
81
  *
82
  * @since 4.4.3
83
- *
84
  * @var ES_Workflow_Trigger
85
  */
86
  public $trigger;
@@ -123,7 +123,7 @@ abstract class ES_Workflow_Action {
123
  * Method to load the action's fields.
124
  *
125
  * @since 4.4.1
126
- *
127
  * @modified 4.5.3 Removed dependency to modify child action file to load extra fields.
128
  */
129
  public function load_fields() {}
@@ -260,11 +260,11 @@ abstract class ES_Workflow_Action {
260
  * Gets the action's fields.
261
  *
262
  * @return ES_Field[]
263
- *
264
  * @since 4.4.1
265
- *
266
  * @modified 4.4.3 Removed isset condition to allow latest list of fields every time when called.
267
- *
268
  * @modified 4.5.3 Added new action action_name_load_extra_fileds to allow loading of extra fields for action.
269
  */
270
  public function get_fields() {
@@ -298,7 +298,7 @@ abstract class ES_Workflow_Action {
298
  *
299
  * @return mixed Will vary depending on the field type specified in the action's fields.
300
  */
301
- public function get_option( $field_name, $process_variables = false, $allow_html = false ) {
302
 
303
  $value = $this->get_option_raw( $field_name );
304
 
80
  * This prop may not be set depending on the context.
81
  *
82
  * @since 4.4.3
83
+ *
84
  * @var ES_Workflow_Trigger
85
  */
86
  public $trigger;
123
  * Method to load the action's fields.
124
  *
125
  * @since 4.4.1
126
+ *
127
  * @modified 4.5.3 Removed dependency to modify child action file to load extra fields.
128
  */
129
  public function load_fields() {}
260
  * Gets the action's fields.
261
  *
262
  * @return ES_Field[]
263
+ *
264
  * @since 4.4.1
265
+ *
266
  * @modified 4.4.3 Removed isset condition to allow latest list of fields every time when called.
267
+ *
268
  * @modified 4.5.3 Added new action action_name_load_extra_fileds to allow loading of extra fields for action.
269
  */
270
  public function get_fields() {
298
  *
299
  * @return mixed Will vary depending on the field type specified in the action's fields.
300
  */
301
+ public function get_option( $field_name, $process_variables = false, $allow_html = false ) {
302
 
303
  $value = $this->get_option_raw( $field_name );
304
 
lite/includes/workflows/abstracts/class-es-workflow-trigger.php CHANGED
@@ -157,7 +157,7 @@ abstract class ES_Workflow_Trigger {
157
  * Field loader
158
  *
159
  * @since 4.4.1
160
- *
161
  * @modified 4.5.3 Added new action trigger_name_load_extra_fields to allow loading of extra fields for given trigger.
162
  */
163
  public function maybe_load_fields() {
@@ -188,7 +188,7 @@ abstract class ES_Workflow_Trigger {
188
  * Add trigger option field
189
  *
190
  * @param object $option Option object.
191
- *
192
  * @since 4.4.6
193
  */
194
  public function add_field( $option ) {
@@ -212,7 +212,7 @@ abstract class ES_Workflow_Trigger {
212
  * @param string $name Field name.
213
  *
214
  * @return ES_Field|false
215
- *
216
  * @since 4.4.6
217
  */
218
  public function get_field( $name ) {
@@ -238,13 +238,13 @@ abstract class ES_Workflow_Trigger {
238
 
239
  /**
240
  * Check if there are active workflow for this trigger
241
- *
242
  * @return bool
243
- *
244
  * @since 4.6.10
245
  */
246
  public function has_workflows() {
247
-
248
  $workflow_query = new ES_Workflow_Query();
249
  $workflow_query->set_triggers( $this->get_name() );
250
 
157
  * Field loader
158
  *
159
  * @since 4.4.1
160
+ *
161
  * @modified 4.5.3 Added new action trigger_name_load_extra_fields to allow loading of extra fields for given trigger.
162
  */
163
  public function maybe_load_fields() {
188
  * Add trigger option field
189
  *
190
  * @param object $option Option object.
191
+ *
192
  * @since 4.4.6
193
  */
194
  public function add_field( $option ) {
212
  * @param string $name Field name.
213
  *
214
  * @return ES_Field|false
215
+ *
216
  * @since 4.4.6
217
  */
218
  public function get_field( $name ) {
238
 
239
  /**
240
  * Check if there are active workflow for this trigger
241
+ *
242
  * @return bool
243
+ *
244
  * @since 4.6.10
245
  */
246
  public function has_workflows() {
247
+
248
  $workflow_query = new ES_Workflow_Query();
249
  $workflow_query->set_triggers( $this->get_name() );
250
 
lite/includes/workflows/abstracts/class-ig-es-workflow-variable.php CHANGED
@@ -6,14 +6,13 @@ if ( ! defined( 'ABSPATH' ) ) {
6
 
7
  /**
8
  * Base class for workflow placeholder variables
9
- *
10
  */
11
  abstract class IG_ES_Workflow_Variable {
12
 
13
  /**
14
  * Variable name
15
  * wc_order.id, cart.link, user.first_name etc
16
- *
17
  * @var string
18
  */
19
  protected $name;
@@ -35,22 +34,22 @@ abstract class IG_ES_Workflow_Variable {
35
  /**
36
  * Variable data type
37
  * e.g. wc_order in wc_order.id, cart in cart.link, user in user.first_name etc
38
- *
39
  * @var string
40
  */
41
  protected $data_type;
42
 
43
- /**
44
  * Variable data field
45
  * e.g. id in wc_order.id, link in cart.link, first_name in user.first_name etc
46
- *
47
  * @var string
48
  */
49
  protected $data_field;
50
 
51
  /**
52
  * Does variable support fallback value in case no value is found
53
- *
54
  * @var bool
55
  */
56
  public $use_fallback = true;
@@ -97,14 +96,14 @@ abstract class IG_ES_Workflow_Variable {
97
  * @param $name
98
  */
99
  public function setup( $name ) {
100
- $this->name = $name;
101
  list( $this->data_type, $this->data_field ) = explode( '.', $this->name );
102
  }
103
 
104
 
105
  /**
106
  * Get variable description
107
- *
108
  * @return string
109
  */
110
  public function get_description() {
@@ -126,7 +125,7 @@ abstract class IG_ES_Workflow_Variable {
126
 
127
  /**
128
  * Get variable name
129
- *
130
  * @return string
131
  */
132
  public function get_name() {
@@ -136,7 +135,7 @@ abstract class IG_ES_Workflow_Variable {
136
 
137
  /**
138
  * Get variable data type
139
- *
140
  * @return string
141
  */
142
  public function get_data_type() {
@@ -146,7 +145,7 @@ abstract class IG_ES_Workflow_Variable {
146
 
147
  /**
148
  * Get variable data field
149
- *
150
  * @return string
151
  */
152
  public function get_data_field() {
6
 
7
  /**
8
  * Base class for workflow placeholder variables
 
9
  */
10
  abstract class IG_ES_Workflow_Variable {
11
 
12
  /**
13
  * Variable name
14
  * wc_order.id, cart.link, user.first_name etc
15
+ *
16
  * @var string
17
  */
18
  protected $name;
34
  /**
35
  * Variable data type
36
  * e.g. wc_order in wc_order.id, cart in cart.link, user in user.first_name etc
37
+ *
38
  * @var string
39
  */
40
  protected $data_type;
41
 
42
+ /**
43
  * Variable data field
44
  * e.g. id in wc_order.id, link in cart.link, first_name in user.first_name etc
45
+ *
46
  * @var string
47
  */
48
  protected $data_field;
49
 
50
  /**
51
  * Does variable support fallback value in case no value is found
52
+ *
53
  * @var bool
54
  */
55
  public $use_fallback = true;
96
  * @param $name
97
  */
98
  public function setup( $name ) {
99
+ $this->name = $name;
100
  list( $this->data_type, $this->data_field ) = explode( '.', $this->name );
101
  }
102
 
103
 
104
  /**
105
  * Get variable description
106
+ *
107
  * @return string
108
  */
109
  public function get_description() {
125
 
126
  /**
127
  * Get variable name
128
+ *
129
  * @return string
130
  */
131
  public function get_name() {
135
 
136
  /**
137
  * Get variable data type
138
+ *
139
  * @return string
140
  */
141
  public function get_data_type() {
145
 
146
  /**
147
  * Get variable data field
148
+ *
149
  * @return string
150
  */
151
  public function get_data_field() {
lite/includes/workflows/actions/abstracts/class-ig-es-action-send-email-abstract.php CHANGED
@@ -13,17 +13,17 @@ if ( ! defined( 'ABSPATH' ) ) {
13
 
14
  /**
15
  * Abstract class for send email workflow action
16
- *
17
  * @class ES_Action_Send_Email_Abstract
18
- *
19
  * @since 4.5.3
20
  */
21
  abstract class ES_Action_Send_Email_Abstract extends ES_Workflow_Action {
22
 
23
  /**
24
  * Load admin props.
25
- *
26
- * @since 4.5.3
27
  */
28
  public function load_admin_details() {
29
  $this->group = __( 'Email', 'email-subscribers' );
@@ -31,7 +31,7 @@ abstract class ES_Action_Send_Email_Abstract extends ES_Workflow_Action {
31
 
32
  /**
33
  * Load fields.
34
- *
35
  * @since 4.5.3
36
  */
37
  public function load_fields() {
13
 
14
  /**
15
  * Abstract class for send email workflow action
16
+ *
17
  * @class ES_Action_Send_Email_Abstract
18
+ *
19
  * @since 4.5.3
20
  */
21
  abstract class ES_Action_Send_Email_Abstract extends ES_Workflow_Action {
22
 
23
  /**
24
  * Load admin props.
25
+ *
26
+ * @since 4.5.3
27
  */
28
  public function load_admin_details() {
29
  $this->group = __( 'Email', 'email-subscribers' );
31
 
32
  /**
33
  * Load fields.
34
+ *
35
  * @since 4.5.3
36
  */
37
  public function load_fields() {
lite/includes/workflows/actions/class-es-action-add-to-list.php CHANGED
@@ -142,11 +142,11 @@ class ES_Action_Add_To_List extends ES_Workflow_Action {
142
 
143
  /**
144
  * Create contact list from product
145
- *
146
  * @param WC_Product $product Product object.
147
- *
148
  * @return int $list_id List ID.
149
- *
150
  * @since 4.4.3
151
  */
152
  public function create_list_from_product( $product ) {
@@ -159,7 +159,7 @@ class ES_Action_Add_To_List extends ES_Workflow_Action {
159
 
160
  $product_name = $product->get_name();
161
  $product_sku = $product->get_sku();
162
-
163
  $list_name = $product_name;
164
 
165
  if ( empty( $product_sku ) ) {
@@ -167,7 +167,7 @@ class ES_Action_Add_To_List extends ES_Workflow_Action {
167
  } else {
168
  $list_slug = $product_sku;
169
  }
170
-
171
  $list = ES()->lists_db->get_list_by_slug( $list_slug );
172
  if ( ! empty( $list ) ) {
173
  $list_id = $list['id'];
142
 
143
  /**
144
  * Create contact list from product
145
+ *
146
  * @param WC_Product $product Product object.
147
+ *
148
  * @return int $list_id List ID.
149
+ *
150
  * @since 4.4.3
151
  */
152
  public function create_list_from_product( $product ) {
159
 
160
  $product_name = $product->get_name();
161
  $product_sku = $product->get_sku();
162
+
163
  $list_name = $product_name;
164
 
165
  if ( empty( $product_sku ) ) {
167
  } else {
168
  $list_slug = $product_sku;
169
  }
170
+
171
  $list = ES()->lists_db->get_list_by_slug( $list_slug );
172
  if ( ! empty( $list ) ) {
173
  $list_id = $list['id'];
lite/includes/workflows/actions/class-es-action-delete-contact.php CHANGED
@@ -49,9 +49,9 @@ class ES_Action_Delete_Contact extends ES_Workflow_Action {
49
 
50
  $data = array();
51
  if ( is_callable( array( $data_type, 'get_data' ) ) ) {
52
- $data = $data_type->get_data( $data_item );
53
  }
54
-
55
  $email = ! empty( $data['email'] ) ? $data['email'] : '';
56
 
57
  if ( ! empty( $email ) ) {
49
 
50
  $data = array();
51
  if ( is_callable( array( $data_type, 'get_data' ) ) ) {
52
+ $data = $data_type->get_data( $data_item );
53
  }
54
+
55
  $email = ! empty( $data['email'] ) ? $data['email'] : '';
56
 
57
  if ( ! empty( $email ) ) {
lite/includes/workflows/admin/class-es-workflow-admin-ajax.php CHANGED
@@ -25,7 +25,7 @@ class ES_Workflow_Admin_Ajax {
25
  * Hook in methods
26
  *
27
  * @since 4.4.1
28
- *
29
  * @since 4.6.9 Added modal_variable_info ajax event.
30
  */
31
  public static function init() {
@@ -147,19 +147,22 @@ class ES_Workflow_Admin_Ajax {
147
 
148
  /**
149
  * Show vairable info modal
150
- *
151
  * @since 4.6.9
152
  */
153
  public static function modal_variable_info() {
154
-
155
  check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' );
156
-
157
  $variable = IG_ES_Variables::get_variable( ES_Clean::string( ig_es_get_request_data( 'variable' ) ) );
158
 
159
  if ( $variable ) {
160
- ES_Workflow_Admin::get_view( 'modal-variable-info', array(
161
- 'variable' => $variable
162
- ));
 
 
 
163
  die;
164
  }
165
 
25
  * Hook in methods
26
  *
27
  * @since 4.4.1
28
+ *
29
  * @since 4.6.9 Added modal_variable_info ajax event.
30
  */
31
  public static function init() {
147
 
148
  /**
149
  * Show vairable info modal
150
+ *
151
  * @since 4.6.9
152
  */
153
  public static function modal_variable_info() {
154
+
155
  check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' );
156
+
157
  $variable = IG_ES_Variables::get_variable( ES_Clean::string( ig_es_get_request_data( 'variable' ) ) );
158
 
159
  if ( $variable ) {
160
+ ES_Workflow_Admin::get_view(
161
+ 'modal-variable-info',
162
+ array(
163
+ 'variable' => $variable,
164
+ )
165
+ );
166
  die;
167
  }
168
 
lite/includes/workflows/admin/class-es-workflow-admin-edit.php CHANGED
@@ -212,11 +212,11 @@ class ES_Workflow_Admin_Edit {
212
  $workflow_title = self::$workflow ? self::$workflow->get_title() : '';
213
  $workflows_page_url = menu_page_url( 'es_workflows', false );
214
 
215
- $action = ig_es_get_request_data( 'action' );
216
  if ( 'new' === $action ) {
217
- $title = __( ' Add New Workflow', 'email-subscribers' );
218
  } else {
219
- $title = __( ' Edit Workflow', 'email-subscribers' );
220
  }
221
  ?>
222
  <div class="max-w-full -mt-3 font-sans">
@@ -226,7 +226,7 @@ class ES_Workflow_Admin_Edit {
226
  <nav class="text-gray-400 my-0" aria-label="Breadcrumb">
227
  <ol class="list-none p-0 inline-flex">
228
  <li class="flex items-center text-sm tracking-wide">
229
- <a class="hover:underline" href="<?php echo esc_url( $workflows_page_url ); ?>"><?php esc_html_e('Workflows', 'email-subscribers'); ?></a>
230
  <svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
231
  </li>
232
  </ol>
@@ -288,7 +288,7 @@ class ES_Workflow_Admin_Edit {
288
  add_meta_box( 'ig_es_workflow_actions', __( 'Actions', 'email-subscribers' ), array( __CLASS__, 'actions_metabox' ), $page_prefix . '_page_es_workflows', 'normal', 'default' );
289
  add_meta_box( 'ig_es_workflow_save', __( 'Save', 'email-subscribers' ), array( __CLASS__, 'save_metabox' ), $page_prefix . '_page_es_workflows', 'side', 'default' );
290
  add_meta_box( 'ig_es_workflow_variables', __( 'Placeholders', 'email-subscribers' ), array( __CLASS__, 'variables_metabox' ), $page_prefix . '_page_es_workflows', 'side', 'default' );
291
-
292
  if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
293
  do_action( 'ig_es_workflows_integration', $page_prefix );
294
  }
@@ -296,33 +296,33 @@ class ES_Workflow_Admin_Edit {
296
 
297
  /**
298
  * Method to remove screen options tab on workflow edit page.
299
- *
300
  * @param bool $show_screen_options
301
- *
302
  * @return bool $show_screen_options
303
- *
304
  * @since 4.6.1
305
  */
306
  public static function remove_screen_options( $show_screen_options ) {
307
-
308
  $show_screen_options = false;
309
  return $show_screen_options;
310
  }
311
 
312
  /**
313
  * Method to forcefully show ES workflow metaboxes if user has hidden them from screen options.
314
- *
315
  * @param array $hidden An array of IDs of hidden meta boxes.
316
  * @param WP_Screen $screen WP_Screen object of the current screen.
317
  * @param bool $use_defaults Whether to show the default meta boxes.
318
  * Default true.
319
- *
320
  * @return array $hidden
321
- *
322
  * @since 4.6.1
323
  */
324
  public static function show_hidden_workflow_metaboxes( $hidden, $screen, $use_defaults ) {
325
-
326
  $es_workflow_metaboxes = array(
327
  'ig_es_workflow_trigger',
328
  'ig_es_workflow_actions',
@@ -336,7 +336,7 @@ class ES_Workflow_Admin_Edit {
336
  // Remove ES workflows metaboxes from the user's hidden metabox list.
337
  $hidden = array_diff( $hidden, $es_workflow_metaboxes );
338
  }
339
-
340
  return $hidden;
341
  }
342
 
@@ -374,7 +374,7 @@ class ES_Workflow_Admin_Edit {
374
  'meta-box-actions',
375
  array(
376
  'workflow' => self::$workflow,
377
- 'workflow_actions' => self::$workflow ? self::$workflow->get_actions(): false,
378
  'action_select_box_values' => $action_select_box_values,
379
  )
380
  );
@@ -442,7 +442,7 @@ class ES_Workflow_Admin_Edit {
442
  * @since 4.4.1
443
  * @param int $workflow_id Workflow ID.
444
  * @return mixed $workflow_id/false workflow id on success otherwise false
445
- *
446
  * @since 4.5.3 Removed sanitization for $posted being performed through ig_es_get_request_data function. Instead added individual sanitization based on workflow field.
447
  */
448
  public static function save( $workflow_id = 0 ) {
@@ -455,11 +455,11 @@ class ES_Workflow_Admin_Edit {
455
 
456
  $workflow_title = isset( $posted['title'] ) ? ig_es_clean( $posted['title'] ) : '';
457
  $workflow_name = ! empty( $workflow_title ) ? sanitize_title( ES_Clean::string( $workflow_title ) ) : '';
458
- $trigger_name = isset( $posted['trigger_name'] ) ? ig_es_clean( $posted['trigger_name'] ): '';
459
- $trigger_options = isset( $posted['trigger_options'] ) ? ig_es_clean( $posted['trigger_options'] ): array();
460
  $rules = isset( $posted['rules'] ) ? ig_es_clean( $posted['rules'] ) : array();
461
  $actions = isset( $posted['actions'] ) ? $posted['actions'] : array(); // We can't sanitize actions data since some actions like Send email allows html in its field.
462
- $status = isset( $posted['status'] ) ? ig_es_clean( $posted['status'] ): 0;
463
  $type = isset( $posted['type'] ) ? ig_es_clean( $posted['type'] ) : 0;
464
  $priority = isset( $posted['priority'] ) ? ig_es_clean( $posted['priority'] ) : 0;
465
 
212
  $workflow_title = self::$workflow ? self::$workflow->get_title() : '';
213
  $workflows_page_url = menu_page_url( 'es_workflows', false );
214
 
215
+ $action = ig_es_get_request_data( 'action' );
216
  if ( 'new' === $action ) {
217
+ $title = __( ' Add New Workflow', 'email-subscribers' );
218
  } else {
219
+ $title = __( ' Edit Workflow', 'email-subscribers' );
220
  }
221
  ?>
222
  <div class="max-w-full -mt-3 font-sans">
226
  <nav class="text-gray-400 my-0" aria-label="Breadcrumb">
227
  <ol class="list-none p-0 inline-flex">
228
  <li class="flex items-center text-sm tracking-wide">
229
+ <a class="hover:underline" href="<?php echo esc_url( $workflows_page_url ); ?>"><?php esc_html_e( 'Workflows', 'email-subscribers' ); ?></a>
230
  <svg class="fill-current w-2.5 h-2.5 mx-2 mt-mx" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
231
  </li>
232
  </ol>
288
  add_meta_box( 'ig_es_workflow_actions', __( 'Actions', 'email-subscribers' ), array( __CLASS__, 'actions_metabox' ), $page_prefix . '_page_es_workflows', 'normal', 'default' );
289
  add_meta_box( 'ig_es_workflow_save', __( 'Save', 'email-subscribers' ), array( __CLASS__, 'save_metabox' ), $page_prefix . '_page_es_workflows', 'side', 'default' );
290
  add_meta_box( 'ig_es_workflow_variables', __( 'Placeholders', 'email-subscribers' ), array( __CLASS__, 'variables_metabox' ), $page_prefix . '_page_es_workflows', 'side', 'default' );
291
+
292
  if ( ES()->can_upsell_features( array( 'lite', 'trial' ) ) ) {
293
  do_action( 'ig_es_workflows_integration', $page_prefix );
294
  }
296
 
297
  /**
298
  * Method to remove screen options tab on workflow edit page.
299
+ *
300
  * @param bool $show_screen_options
301
+ *
302
  * @return bool $show_screen_options
303
+ *
304
  * @since 4.6.1
305
  */
306
  public static function remove_screen_options( $show_screen_options ) {
307
+
308
  $show_screen_options = false;
309
  return $show_screen_options;
310
  }
311
 
312
  /**
313
  * Method to forcefully show ES workflow metaboxes if user has hidden them from screen options.
314
+ *
315
  * @param array $hidden An array of IDs of hidden meta boxes.
316
  * @param WP_Screen $screen WP_Screen object of the current screen.
317
  * @param bool $use_defaults Whether to show the default meta boxes.
318
  * Default true.
319
+ *
320
  * @return array $hidden
321
+ *
322
  * @since 4.6.1
323
  */
324
  public static function show_hidden_workflow_metaboxes( $hidden, $screen, $use_defaults ) {
325
+
326
  $es_workflow_metaboxes = array(
327
  'ig_es_workflow_trigger',
328
  'ig_es_workflow_actions',
336
  // Remove ES workflows metaboxes from the user's hidden metabox list.
337
  $hidden = array_diff( $hidden, $es_workflow_metaboxes );
338
  }
339
+
340
  return $hidden;
341
  }
342
 
374
  'meta-box-actions',
375
  array(
376
  'workflow' => self::$workflow,
377
+ 'workflow_actions' => self::$workflow ? self::$workflow->get_actions() : false,
378
  'action_select_box_values' => $action_select_box_values,
379
  )
380
  );
442
  * @since 4.4.1
443
  * @param int $workflow_id Workflow ID.
444
  * @return mixed $workflow_id/false workflow id on success otherwise false
445
+ *
446
  * @since 4.5.3 Removed sanitization for $posted being performed through ig_es_get_request_data function. Instead added individual sanitization based on workflow field.
447
  */
448
  public static function save( $workflow_id = 0 ) {
455
 
456
  $workflow_title = isset( $posted['title'] ) ? ig_es_clean( $posted['title'] ) : '';
457
  $workflow_name = ! empty( $workflow_title ) ? sanitize_title( ES_Clean::string( $workflow_title ) ) : '';
458
+ $trigger_name = isset( $posted['trigger_name'] ) ? ig_es_clean( $posted['trigger_name'] ) : '';
459
+ $trigger_options = isset( $posted['trigger_options'] ) ? ig_es_clean( $posted['trigger_options'] ) : array();
460
  $rules = isset( $posted['rules'] ) ? ig_es_clean( $posted['rules'] ) : array();
461
  $actions = isset( $posted['actions'] ) ? $posted['actions'] : array(); // We can't sanitize actions data since some actions like Send email allows html in its field.
462
+ $status = isset( $posted['status'] ) ? ig_es_clean( $posted['status'] ) : 0;
463
  $type = isset( $posted['type'] ) ? ig_es_clean( $posted['type'] ) : 0;
464
  $priority = isset( $posted['priority'] ) ? ig_es_clean( $posted['priority'] ) : 0;
465
 
lite/includes/workflows/admin/views/meta-box-trigger.php CHANGED
@@ -25,7 +25,7 @@ if ( ! ES()->is_starter() ) {
25
  'ig_es_cf7_submitted' => __( 'Contact Form 7 Submitted', 'email-subscribers' ),
26
  'ig_es_wpforms_submitted' => __( 'WP Form Submitted', 'email-subscribers' ),
27
  'ig_es_ninja_forms_submitted' => __( 'Ninja Form Submitted', 'email-subscribers' ),
28
- 'ig_es_gravity_forms_submitted' => __( 'Gravity Form Submitted', 'email-subscribers' ),
29
  'ig_es_forminator_forms_submitted' => __( 'Forminator Form Submitted', 'email-subscribers' ),
30
  ),
31
  'Order' => array(
@@ -40,25 +40,25 @@ if ( ! ES()->is_starter() ) {
40
 
41
  if ( ! ES()->is_pro() ) {
42
  $pro_trigger_list = array(
43
- 'Comment' => array(
44
  'ig_es_wc_product_review_approved' => __( 'New Product Review Posted', 'email-subscribers' ),
45
  ),
46
- 'Order' => array(
47
  'ig_es_wc_order_refunded' => __( 'WooCommerce Order Refunded', 'email-subscribers' ),
48
  ),
49
- 'Wishlists' => array(
50
  'ig_es_yith_wc_wishlist' => __( 'Wishlist Item On Sale (YITH Wishlists)', 'email-subscribers' ),
51
  ),
52
- 'Carts' => array(
53
- 'ig_es_wc_cart_abandoned' => __( 'Cart Abandoned', 'email-subscribers' ),
54
- 'ig_es_wc_cart_abandoned_registered_users' => __( 'Cart Abandoned - Registered Users Only', 'email-subscribers' ),
55
- 'ig_es_wc_cart_abandoned_guests_users' => __( 'Cart Abandoned - Guests Only', 'email-subscribers' ),
56
  ),
57
- 'User' => array(
58
  'ig_es_user_role_changed' => __( 'User Role Changed', 'email-subscribers' ),
59
  ),
60
  );
61
- $trigger_list = array_merge_recursive( $trigger_list, $pro_trigger_list );
62
  }
63
  ?>
64
  <table class="ig-es-table">
25
  'ig_es_cf7_submitted' => __( 'Contact Form 7 Submitted', 'email-subscribers' ),
26
  'ig_es_wpforms_submitted' => __( 'WP Form Submitted', 'email-subscribers' ),
27
  'ig_es_ninja_forms_submitted' => __( 'Ninja Form Submitted', 'email-subscribers' ),
28
+ 'ig_es_gravity_forms_submitted' => __( 'Gravity Form Submitted', 'email-subscribers' ),
29
  'ig_es_forminator_forms_submitted' => __( 'Forminator Form Submitted', 'email-subscribers' ),
30
  ),
31
  'Order' => array(
40
 
41
  if ( ! ES()->is_pro() ) {
42
  $pro_trigger_list = array(
43
+ 'Comment' => array(
44
  'ig_es_wc_product_review_approved' => __( 'New Product Review Posted', 'email-subscribers' ),
45
  ),
46
+ 'Order' => array(
47
  'ig_es_wc_order_refunded' => __( 'WooCommerce Order Refunded', 'email-subscribers' ),
48
  ),
49
+ 'Wishlists' => array(
50
  'ig_es_yith_wc_wishlist' => __( 'Wishlist Item On Sale (YITH Wishlists)', 'email-subscribers' ),
51
  ),
52
+ 'Carts' => array(
53
+ 'ig_es_wc_cart_abandoned' => __( 'Cart Abandoned', 'email-subscribers' ),
54
+ 'ig_es_wc_cart_abandoned_registered_users' => __( 'Cart Abandoned - Registered Users Only', 'email-subscribers' ),
55
+ 'ig_es_wc_cart_abandoned_guests_users' => __( 'Cart Abandoned - Guests Only', 'email-subscribers' ),
56
  ),
57
+ 'User' => array(
58
  'ig_es_user_role_changed' => __( 'User Role Changed', 'email-subscribers' ),
59
  ),
60
  );
61
+ $trigger_list = array_merge_recursive( $trigger_list, $pro_trigger_list );
62
  }
63
  ?>
64
  <table class="ig-es-table">
lite/includes/workflows/admin/views/meta-box-variables.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
  /**
3
  * ES_Workflow object
4
- *
5
  * @var ES_Workflow $workflow
6
  */
7
 
8
- if ( ! defined( 'ABSPATH' ) ) {
9
  exit;
10
  }
11
 
1
  <?php
2
  /**
3
  * ES_Workflow object
4
+ *
5
  * @var ES_Workflow $workflow
6
  */
7
 
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
  exit;
10
  }
11
 
lite/includes/workflows/admin/views/modal-variable-info.php CHANGED
@@ -1,12 +1,12 @@
1
  <?php
2
 
3
- if ( ! defined( 'ABSPATH' ) ) {
4
  exit;
5
  }
6
 
7
  /**
8
  * IG_ES_Variable object
9
- *
10
  * @var IG_ES_Variable $variable
11
  */
12
 
@@ -29,7 +29,7 @@ if ( ! defined( 'ABSPATH' ) ) {
29
 
30
  <tr class="ig-es-table__row ig-es-workflow-variables-parameter-row"
31
  data-parameter-name="<?php echo esc_attr( $field->get_name() ); ?>"
32
- <?php
33
  if ( isset( $field->meta['show'] ) ) :
34
  ?>
35
  data-parameter-show="<?php echo esc_attr( $field->meta['show'] ); ?>"<?php endif; ?>
@@ -38,7 +38,7 @@ if ( ! defined( 'ABSPATH' ) ) {
38
 
39
  <td class="ig-es-table__col ig-es-table__col--label">
40
  <strong><?php echo esc_html( $field->get_name() ); ?></strong>
41
- <?php
42
  if ( $field->get_required() ) :
43
  ?>
44
  <span class="ig-es-required-asterisk"></span><?php endif; ?>
1
  <?php
2
 
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
  exit;
5
  }
6
 
7
  /**
8
  * IG_ES_Variable object
9
+ *
10
  * @var IG_ES_Variable $variable
11
  */
12
 
29
 
30
  <tr class="ig-es-table__row ig-es-workflow-variables-parameter-row"
31
  data-parameter-name="<?php echo esc_attr( $field->get_name() ); ?>"
32
+ <?php
33
  if ( isset( $field->meta['show'] ) ) :
34
  ?>
35
  data-parameter-show="<?php echo esc_attr( $field->meta['show'] ); ?>"<?php endif; ?>
38
 
39
  <td class="ig-es-table__col ig-es-table__col--label">
40
  <strong><?php echo esc_html( $field->get_name() ); ?></strong>
41
+ <?php
42
  if ( $field->get_required() ) :
43
  ?>
44
  <span class="ig-es-required-asterisk"></span><?php endif; ?>
lite/includes/workflows/class-es-clean.php CHANGED
@@ -134,7 +134,7 @@ class ES_Clean {
134
  * @param string $content
135
  *
136
  * @return string $content
137
- *
138
  * @since 4.5.3
139
  */
140
  public static function editor_content( $content ) {
134
  * @param string $content
135
  *
136
  * @return string $content
137
+ *
138
  * @since 4.5.3
139
  */
140
  public static function editor_content( $content ) {
lite/language.php CHANGED
@@ -756,6 +756,7 @@ __( 'Email has been sent. Please check your inbox', 'email-subscribers' ),
756
  __( 'Email Subscribers Widget', 'email-subscribers' ),
757
  __( 'Yes', 'email-subscribers' ),
758
  __( 'No', 'email-subscribers' ),
 
759
  __( 'Allow Email Subscribers to track plugin usage. It will help us to understand your issue better. We guarantee no sensitive data is collected.', 'email-subscribers' ),
760
  __( 'Not a member yet?', 'email-subscribers' ),
761
  __( 'Join', 'email-subscribers' ),
756
  __( 'Email Subscribers Widget', 'email-subscribers' ),
757
  __( 'Yes', 'email-subscribers' ),
758
  __( 'No', 'email-subscribers' ),
759
+ __( 'Email Subscribers & Newsletter', 'email-subscribers' ),
760
  __( 'Allow Email Subscribers to track plugin usage. It will help us to understand your issue better. We guarantee no sensitive data is collected.', 'email-subscribers' ),
761
  __( 'Not a member yet?', 'email-subscribers' ),
762
  __( 'Join', 'email-subscribers' ),
lite/languages/email-subscribers.pot CHANGED
@@ -2,14 +2,14 @@
2
  # This file is distributed under the same license as the Email Subscribers & Newsletters plugin.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Email Subscribers & Newsletters 4.8.1\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/email-subscribers\n"
7
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
8
  "Language-Team: LANGUAGE <LL@li.org>\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
- "POT-Creation-Date: 2021-09-15T12:18:45+02:00\n"
13
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
  "X-Generator: WP-CLI 2.4.0\n"
15
  "X-Domain: email-subscribers\n"
@@ -29,225 +29,225 @@ msgstr ""
29
 
30
  #. Author of the plugin
31
  #: lite/admin/partials/help.php:28
32
- #: lite/includes/class-email-subscribers.php:1548
33
  msgid "Icegram"
34
  msgstr ""
35
 
36
  #. translators: %s: PHP version
37
- #: email-subscribers.php:51
38
  msgid "Email Subscribers requires PHP version %s+, plugin is currently NOT RUNNING."
39
  msgstr ""
40
 
41
  #. translators: %s: Link to Email Subscribers Premium upgrade
42
- #: email-subscribers.php:116
43
  msgid "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."
44
  msgstr ""
45
 
46
- #: email-subscribers.php:117
47
  msgid "Email Subscribers Premium"
48
  msgstr ""
49
 
50
- #: email-subscribers.php:227
51
  msgid "Email Subscribers requires WooCommerce to be installed and active, plugin is currently NOT RUNNING."
52
  msgstr ""
53
 
54
- #: lite/admin/class-email-subscribers-admin.php:168
55
  msgid "An error has occured. Please try again later."
56
  msgstr ""
57
 
58
- #: lite/admin/class-email-subscribers-admin.php:169
59
  msgid "Broadcast saved successfully."
60
  msgstr ""
61
 
62
- #: lite/admin/class-email-subscribers-admin.php:170
63
  msgid "An error has occured while saving the broadcast. Please try again later."
64
  msgstr ""
65
 
66
- #: lite/admin/class-email-subscribers-admin.php:171
67
  msgid "Please add a broadcast subject before saving."
68
  msgstr ""
69
 
70
- #: lite/admin/class-email-subscribers-admin.php:172
71
  #: pro/pro-class-email-subscribers.php:504
72
  msgid "Please add email body."
73
  msgstr ""
74
 
75
- #: lite/admin/class-email-subscribers-admin.php:173
76
  msgid "Do you really like to remove all conditions?"
77
  msgstr ""
78
 
79
- #: lite/admin/class-email-subscribers-admin.php:176
80
  msgid "Please select a trigger before saving the workflow."
81
  msgstr ""
82
 
83
- #: lite/admin/class-email-subscribers-admin.php:177
84
  msgid "Please add some actions before saving the workflow."
85
  msgstr ""
86
 
87
- #: lite/admin/class-email-subscribers-admin.php:178
88
  msgid "Please select an action that this workflow should perform before saving the workflow."
89
  msgstr ""
90
 
91
- #: lite/admin/class-email-subscribers-admin.php:179
92
  msgid "Changing the trigger will remove existing actions. Do you want to proceed anyway?."
93
  msgstr ""
94
 
95
- #: lite/admin/class-email-subscribers-admin.php:180
96
  msgid "Copied!"
97
  msgstr ""
98
 
99
- #: lite/admin/class-email-subscribers-admin.php:181
100
  msgid "Are you sure?"
101
  msgstr ""
102
 
103
- #: lite/admin/class-email-subscribers-admin.php:184
104
  msgid "Please select the status for the importing contacts!"
105
  msgstr ""
106
 
107
- #: lite/admin/class-email-subscribers-admin.php:185
108
  msgid "Please select a list for importing contacts!"
109
  msgstr ""
110
 
111
- #: lite/admin/class-email-subscribers-admin.php:186
112
  msgid "Please select the email address column!"
113
  msgstr ""
114
 
115
- #: lite/admin/class-email-subscribers-admin.php:187
116
  msgid "Preparing Data"
117
  msgstr ""
118
 
119
  #. translators: %s: Upload progress
120
- #: lite/admin/class-email-subscribers-admin.php:189
121
  msgid "Uploading...%s"
122
  msgstr ""
123
 
124
  #. translators: %s: Import progress
125
- #: lite/admin/class-email-subscribers-admin.php:191
126
  msgid "Importing contacts...%s"
127
  msgstr ""
128
 
129
  #. translators: %s: Import failed svg icon
130
- #: lite/admin/class-email-subscribers-admin.php:193
131
  msgid "Import failed! %s"
132
  msgstr ""
133
 
134
- #: lite/admin/class-email-subscribers-admin.php:194
135
  msgid "Please do not close this window until it completes..."
136
  msgstr ""
137
 
138
- #: lite/admin/class-email-subscribers-admin.php:195
139
  msgid "Preparing Import..."
140
  msgstr ""
141
 
142
  #. translators: 1. Imported contacts count 2. Total contacts count 3. Failed to import count 4. Memory usage
143
- #: lite/admin/class-email-subscribers-admin.php:197
144
  msgid "Currently %1$s of %2$s imported with %3$s errors. %4$s %5$s memory usage"
145
  msgstr ""
146
 
147
  #. translators: 1 Duplicate found email message
148
- #: lite/admin/class-email-subscribers-admin.php:199
149
  msgid "%1$s duplicate emails found."
150
  msgstr ""
151
 
152
  #. translators: %s: Time left in minutes
153
- #: lite/admin/class-email-subscribers-admin.php:201
154
  msgid "Estimate time left: %s minutes"
155
  msgstr ""
156
 
157
  #. translators: %s: Next attempt delaly time
158
- #: lite/admin/class-email-subscribers-admin.php:203
159
  msgid "Continues in %s seconds"
160
  msgstr ""
161
 
162
- #: lite/admin/class-email-subscribers-admin.php:204
163
  msgid "There was a problem during importing contacts. Please check the error logs for more information!"
164
  msgstr ""
165
 
166
- #: lite/admin/class-email-subscribers-admin.php:205
167
  msgid "Do you really like to import these contacts?"
168
  msgstr ""
169
 
170
  #. translators: %s: Process complete svg icon
171
- #: lite/admin/class-email-subscribers-admin.php:207
172
  msgid "Import complete! %s"
173
  msgstr ""
174
 
175
- #: lite/admin/class-email-subscribers-admin.php:208
176
  msgid "You are currently importing subscribers! If you leave the page all pending subscribers don't get imported!"
177
  msgstr ""
178
 
179
- #: lite/admin/class-email-subscribers-admin.php:209
180
  msgid "API is valid. Fetching lists..."
181
  msgstr ""
182
 
183
- #: lite/admin/class-email-subscribers-admin.php:210
184
  msgid "Fetching contacts from MailChimp...Please do not close this window"
185
  msgstr ""
186
 
187
- #: lite/admin/class-email-subscribers-admin.php:290
188
  #: lite/admin/partials/dashboard.php:100
189
  msgid "Dashboard"
190
  msgstr ""
191
 
192
- #: lite/admin/class-email-subscribers-admin.php:295
193
  #: lite/admin/partials/dashboard.php:107
194
- #: lite/includes/classes/class-es-contacts-table.php:219
195
- #: lite/includes/pro-features.php:154
196
  #: starter/starter-class-email-subscribers.php:646
197
  msgid "Audience"
198
  msgstr ""
199
 
200
- #: lite/admin/class-email-subscribers-admin.php:299
201
  #: lite/includes/classes/class-es-forms-table.php:459
202
  #: lite/includes/classes/class-es-lists-table.php:34
203
  #: lite/includes/classes/class-es-lists-table.php:88
204
  msgid "Lists"
205
  msgstr ""
206
 
207
- #: lite/admin/class-email-subscribers-admin.php:305
208
  #: lite/includes/classes/class-es-form-widget.php:70
209
  #: lite/includes/classes/class-es-forms-table.php:39
210
  #: lite/includes/classes/class-es-forms-table.php:40
211
  #: lite/includes/classes/class-es-forms-table.php:93
212
- #: lite/includes/pro-features.php:155
213
  #: starter/starter-class-email-subscribers.php:647
214
  msgid "Forms"
215
  msgstr ""
216
 
217
- #: lite/admin/class-email-subscribers-admin.php:311
218
  #: lite/includes/classes/class-es-campaigns-table.php:130
219
  #: lite/includes/classes/class-es-newsletters.php:239
220
  #: lite/includes/classes/class-es-newsletters.php:245
221
- #: lite/includes/pro-features.php:156
222
  #: pro/partials/es-dashboard.php:8
223
  #: starter/starter-class-email-subscribers.php:648
224
  msgid "Campaigns"
225
  msgstr ""
226
 
227
- #: lite/admin/class-email-subscribers-admin.php:315
228
  msgid "Post Notifications"
229
  msgstr ""
230
 
231
- #: lite/admin/class-email-subscribers-admin.php:317
232
  #: lite/includes/classes/class-es-campaigns-table.php:362
233
  #: lite/includes/classes/class-es-newsletters.php:254
234
- #: lite/includes/classes/class-es-reports-data.php:353
235
- #: lite/includes/classes/class-es-reports-table.php:163
236
  #: lite/includes/classes/class-es-templates-table.php:282
237
- #: lite/includes/pro-features.php:1123
238
  #: lite/public/class-email-subscribers-public.php:472
239
  #: pro/classes/class-es-pro-reports-data.php:77
240
  msgid "Broadcast"
241
  msgstr ""
242
 
243
- #: lite/admin/class-email-subscribers-admin.php:318
244
  #: lite/includes/classes/class-es-newsletters.php:430
245
- #: lite/includes/classes/class-es-reports-table.php:518
246
  msgid "Template Preview"
247
  msgstr ""
248
 
249
- #: lite/admin/class-email-subscribers-admin.php:325
250
- #: lite/includes/pro-features.php:159
251
  #: lite/includes/workflows/admin/class-es-workflow-admin-edit.php:229
252
  #: lite/includes/workflows/class-es-workflows-table.php:53
253
  #: lite/includes/workflows/class-es-workflows-table.php:169
@@ -255,13 +255,13 @@ msgstr ""
255
  msgid "Workflows"
256
  msgstr ""
257
 
258
- #: lite/admin/class-email-subscribers-admin.php:334
259
  #: lite/admin/partials/dashboard.php:238
260
  #: lite/includes/classes/class-es-campaign-report.php:17
261
  #: lite/includes/classes/class-es-reports-table.php:17
262
- #: lite/includes/classes/class-es-reports-table.php:56
263
- #: lite/includes/classes/class-es-reports-table.php:114
264
- #: lite/includes/pro-features.php:157
265
  #: pro/classes/class-es-pro-sequence-report.php:21
266
  #: pro/classes/class-es-pro-sequence-report.php:44
267
  #: pro/classes/class-es-pro-sequence-report.php:77
@@ -269,80 +269,81 @@ msgstr ""
269
  msgid "Reports"
270
  msgstr ""
271
 
272
- #: lite/admin/class-email-subscribers-admin.php:338
273
  #: lite/admin/partials/dashboard.php:246
274
  #: lite/includes/classes/class-es-admin-settings.php:131
275
  msgid "Settings"
276
  msgstr ""
277
 
278
- #: lite/admin/class-email-subscribers-admin.php:343
279
  msgid "Go To Icegram"
280
  msgstr ""
281
 
282
  #. translators: 1. WordPress URL 2. Email Subscribers version 3. Icegram site URL
283
- #: lite/admin/class-email-subscribers-admin.php:894
284
  msgid "<span id=\"footer-thankyou\">Thank you for creating with <a href=\"%1$s\" target=\"_blank\">WordPress</a> | Email Subscribers <b>%2$s</b>. Developed by team <a href=\"%3$s\" target=\"_blank\">Icegram</a></span>"
285
  msgstr ""
286
 
287
- #: lite/admin/class-email-subscribers-admin.php:922
288
  msgid "Something went wrong"
289
  msgstr ""
290
 
291
- #: lite/admin/class-email-subscribers-admin.php:1295
292
  #: lite/includes/class-email-subscribers-activator.php:61
293
- #: lite/includes/class-email-subscribers.php:1545
294
  #: lite/includes/classes/class-es-form-widget.php:11
295
  #: lite/includes/classes/class-es-old-widget.php:13
296
  #: lite/includes/classes/class-es-old-widget.php:15
297
  #: lite/includes/classes/class-es-widget.php:11
 
298
  msgid "Email Subscribers"
299
  msgstr ""
300
 
301
- #: lite/admin/class-email-subscribers-admin.php:1337
302
  msgid "Last 30 days"
303
  msgstr ""
304
 
305
- #: lite/admin/class-email-subscribers-admin.php:1346
306
- #: lite/includes/class-es-common.php:190
307
- #: lite/includes/classes/class-es-contacts-table.php:332
308
  #: lite/includes/classes/class-es-import-subscribers.php:837
309
- #: lite/includes/classes/class-es-import-subscribers.php:1185
310
  #: lite/includes/classes/class-es-lists-table.php:571
311
  msgid "Subscribed"
312
  msgstr ""
313
 
314
- #: lite/admin/class-email-subscribers-admin.php:1354
315
- #: lite/includes/class-es-common.php:192
316
- #: lite/includes/classes/class-es-contacts-table.php:340
317
  #: lite/includes/classes/class-es-import-subscribers.php:838
318
- #: lite/includes/classes/class-es-import-subscribers.php:1186
319
  #: lite/includes/classes/class-es-lists-table.php:572
320
  #: pro/classes/class-es-pro-reports-data.php:283
321
  msgid "Unsubscribed"
322
  msgstr ""
323
 
324
- #: lite/admin/class-email-subscribers-admin.php:1362
325
- #: lite/includes/pro-features.php:1155
326
  msgid "Avg Open Rate"
327
  msgstr ""
328
 
329
- #: lite/admin/class-email-subscribers-admin.php:1370
330
  #: lite/admin/partials/dashboard.php:193
331
  msgid "Messages Sent"
332
  msgstr ""
333
 
334
- #: lite/admin/class-email-subscribers-admin.php:1381
335
  msgid "Last Campaign"
336
  msgstr ""
337
 
338
- #: lite/admin/class-email-subscribers-admin.php:1417
339
  msgid "Sent to"
340
  msgstr ""
341
 
342
- #: lite/admin/class-email-subscribers-admin.php:1429
343
  #: lite/admin/partials/dashboard.php:177
344
- #: lite/includes/pro-features.php:1235
345
- #: lite/includes/pro-features.php:1273
346
  #: pro/classes/class-es-pro-reports-data.php:321
347
  #: pro/classes/class-es-pro-reports-data.php:444
348
  #: pro/classes/class-es-pro-reports-data.php:677
@@ -351,125 +352,126 @@ msgstr ""
351
  msgid "Opens"
352
  msgstr ""
353
 
354
- #: lite/admin/class-email-subscribers-admin.php:1443
355
  msgid "No campaigns sent yet"
356
  msgstr ""
357
 
358
- #: lite/admin/class-email-subscribers-admin.php:1451
359
  msgid "Latest Blog Posts from Icegram"
360
  msgstr ""
361
 
362
- #: lite/admin/class-ig-es-campaign-rules.php:171
363
  msgid "Recipients"
364
  msgstr ""
365
 
366
- #: lite/admin/class-ig-es-campaign-rules.php:181
367
  msgid "Add recipients"
368
  msgstr ""
369
 
370
- #: lite/admin/class-ig-es-campaign-rules.php:184
371
- #: lite/admin/class-ig-es-campaign-rules.php:257
372
- #: lite/admin/class-ig-es-campaign-rules.php:259
373
- #: lite/admin/class-ig-es-campaign-rules.php:524
374
- #: lite/admin/class-ig-es-campaign-rules.php:529
375
- #: lite/admin/class-ig-es-campaign-rules.php:535
376
- #: lite/admin/class-ig-es-campaign-rules.php:569
377
  msgid "or"
378
  msgstr ""
379
 
380
- #: lite/admin/class-ig-es-campaign-rules.php:186
381
  msgid "remove all"
382
  msgstr ""
383
 
384
- #: lite/admin/class-ig-es-campaign-rules.php:206
385
  msgid "Campaign Rules"
386
  msgstr ""
387
 
388
- #: lite/admin/class-ig-es-campaign-rules.php:210
389
  msgid "Loading..."
390
  msgstr ""
391
 
392
- #: lite/admin/class-ig-es-campaign-rules.php:211
393
  msgid "Save Rules"
394
  msgstr ""
395
 
396
- #: lite/admin/class-ig-es-campaign-rules.php:213
397
  msgid "Close panel"
398
  msgstr ""
399
 
400
- #: lite/admin/class-ig-es-campaign-rules.php:227
401
  msgid "Total recipients"
402
  msgstr ""
403
 
404
- #: lite/admin/class-ig-es-campaign-rules.php:248
405
- #: lite/admin/class-ig-es-campaign-rules.php:419
406
- #: lite/admin/class-ig-es-campaign-rules.php:566
407
  msgid "and"
408
  msgstr ""
409
 
410
- #: lite/admin/class-ig-es-campaign-rules.php:257
411
- #: lite/admin/class-ig-es-campaign-rules.php:382
412
  msgid "Add Condition"
413
  msgstr ""
414
 
415
- #: lite/admin/class-ig-es-campaign-rules.php:260
416
  msgid "remove condition"
417
  msgstr ""
418
 
419
- #: lite/admin/class-ig-es-campaign-rules.php:342
420
- #: lite/admin/class-ig-es-campaign-rules.php:727
421
  msgid "Any campaign"
422
  msgstr ""
423
 
424
- #: lite/admin/class-ig-es-campaign-rules.php:348
425
- #: lite/admin/class-ig-es-campaign-rules.php:366
426
  msgid "no title"
427
  msgstr ""
428
 
429
- #: lite/admin/class-ig-es-campaign-rules.php:361
430
- #: lite/admin/class-ig-es-campaign-rules.php:753
431
  msgid "Any list"
432
  msgstr ""
433
 
434
- #: lite/admin/class-ig-es-campaign-rules.php:370
435
  msgid "No campaigns available"
436
  msgstr ""
437
 
438
- #: lite/admin/class-ig-es-campaign-rules.php:435
439
  msgid " or"
440
  msgstr ""
441
 
442
- #: lite/admin/class-ig-es-campaign-rules.php:445
443
  msgid ") "
444
  msgstr ""
445
 
446
- #: lite/admin/class-ig-es-campaign-rules.php:515
447
  msgctxt "opening curly double quote"
448
  msgid "&#8220;"
449
  msgstr ""
450
 
451
- #: lite/admin/class-ig-es-campaign-rules.php:516
452
  msgctxt "closing curly double quote"
453
  msgid "&#8221;"
454
  msgstr ""
455
 
456
- #: lite/admin/class-ig-es-campaign-rules.php:587
457
  msgid "is in List"
458
  msgstr ""
459
 
460
- #: lite/admin/class-ig-es-campaign-rules.php:604
461
  #: lite/includes/classes/class-es-admin-settings.php:211
462
  #: lite/includes/classes/class-es-campaign-report.php:189
463
- #: lite/includes/classes/class-es-contacts-table.php:788
464
- #: lite/includes/classes/class-es-contacts-table.php:1069
465
  #: lite/includes/classes/class-es-export-subscribers.php:339
466
  #: lite/includes/classes/class-es-forms-table.php:393
467
  #: lite/includes/classes/class-es-import-subscribers.php:563
468
  #: lite/includes/classes/class-es-import-subscribers.php:657
469
- #: lite/includes/classes/class-es-import-subscribers.php:1053
470
- #: lite/includes/classes/class-es-import-subscribers.php:1177
471
- #: lite/includes/pro-features.php:951
472
- #: lite/includes/pro-features.php:1483
 
473
  #: lite/includes/workflows/actions/abstracts/class-ig-es-action-send-email-abstract.php:29
474
  #: lite/public/partials/class-es-shortcode.php:169
475
  #: pro/classes/class-es-pro-campaign-rules.php:35
@@ -479,176 +481,176 @@ msgstr ""
479
  msgid "Email"
480
  msgstr ""
481
 
482
- #: lite/admin/class-ig-es-campaign-rules.php:605
483
- #: lite/includes/pro-features.php:1232
484
- #: lite/includes/pro-features.php:1482
485
  #: pro/classes/class-es-pro-campaign-rules.php:38
486
  #: pro/classes/class-es-pro-reports-data.php:318
487
  msgid "Country"
488
  msgstr ""
489
 
490
- #: lite/admin/class-ig-es-campaign-rules.php:618
491
  #: pro/classes/class-es-pro-campaign-rules.php:43
492
  msgid "has received"
493
  msgstr ""
494
 
495
- #: lite/admin/class-ig-es-campaign-rules.php:619
496
  #: pro/classes/class-es-pro-campaign-rules.php:46
497
  msgid "has not received"
498
  msgstr ""
499
 
500
- #: lite/admin/class-ig-es-campaign-rules.php:620
501
  #: pro/classes/class-es-pro-campaign-rules.php:49
502
  msgid "has received and opened"
503
  msgstr ""
504
 
505
- #: lite/admin/class-ig-es-campaign-rules.php:621
506
  #: pro/classes/class-es-pro-campaign-rules.php:52
507
  msgid "has received but not opened"
508
  msgstr ""
509
 
510
- #: lite/admin/class-ig-es-campaign-rules.php:622
511
  #: pro/classes/class-es-pro-campaign-rules.php:55
512
  msgid "has received and clicked"
513
  msgstr ""
514
 
515
- #: lite/admin/class-ig-es-campaign-rules.php:623
516
  #: pro/classes/class-es-pro-campaign-rules.php:58
517
  msgid "has received and not clicked"
518
  msgstr ""
519
 
520
- #: lite/admin/class-ig-es-campaign-rules.php:635
521
  msgid "Any of the Last 5 Campaigns"
522
  msgstr ""
523
 
524
- #: lite/admin/class-ig-es-campaign-rules.php:636
525
  msgid "Any Campaigns within the last 7 days"
526
  msgstr ""
527
 
528
- #: lite/admin/class-ig-es-campaign-rules.php:637
529
  msgid "Any Campaigns within the last 1 month"
530
  msgstr ""
531
 
532
- #: lite/admin/class-ig-es-campaign-rules.php:638
533
  msgid "Any Campaigns within the last 3 months"
534
  msgstr ""
535
 
536
- #: lite/admin/class-ig-es-campaign-rules.php:639
537
  msgid "Any Campaigns within the last 6 months"
538
  msgstr ""
539
 
540
- #: lite/admin/class-ig-es-campaign-rules.php:640
541
  msgid "Any Campaigns within the last 12 months"
542
  msgstr ""
543
 
544
- #: lite/admin/class-ig-es-campaign-rules.php:652
545
- #: lite/admin/class-ig-es-campaign-rules.php:675
546
- #: lite/admin/class-ig-es-campaign-rules.php:692
547
- #: lite/admin/class-ig-es-campaign-rules.php:711
548
  msgid "is"
549
  msgstr ""
550
 
551
- #: lite/admin/class-ig-es-campaign-rules.php:653
552
- #: lite/admin/class-ig-es-campaign-rules.php:676
553
- #: lite/admin/class-ig-es-campaign-rules.php:693
554
- #: lite/admin/class-ig-es-campaign-rules.php:712
555
  msgid "is not"
556
  msgstr ""
557
 
558
- #: lite/admin/class-ig-es-campaign-rules.php:654
559
- #: lite/admin/class-ig-es-campaign-rules.php:694
560
  msgid "contains"
561
  msgstr ""
562
 
563
- #: lite/admin/class-ig-es-campaign-rules.php:655
564
- #: lite/admin/class-ig-es-campaign-rules.php:695
565
  msgid "contains not"
566
  msgstr ""
567
 
568
- #: lite/admin/class-ig-es-campaign-rules.php:656
569
- #: lite/admin/class-ig-es-campaign-rules.php:696
570
  msgid "begins with"
571
  msgstr ""
572
 
573
- #: lite/admin/class-ig-es-campaign-rules.php:657
574
- #: lite/admin/class-ig-es-campaign-rules.php:697
575
  msgid "ends with"
576
  msgstr ""
577
 
578
- #: lite/admin/class-ig-es-campaign-rules.php:658
579
- #: lite/admin/class-ig-es-campaign-rules.php:677
580
  msgid "is greater than"
581
  msgstr ""
582
 
583
- #: lite/admin/class-ig-es-campaign-rules.php:659
584
- #: lite/admin/class-ig-es-campaign-rules.php:678
585
  msgid "is smaller than"
586
  msgstr ""
587
 
588
- #: lite/admin/class-ig-es-campaign-rules.php:660
589
- #: lite/admin/class-ig-es-campaign-rules.php:679
590
  msgid "is greater or equal"
591
  msgstr ""
592
 
593
- #: lite/admin/class-ig-es-campaign-rules.php:661
594
- #: lite/admin/class-ig-es-campaign-rules.php:680
595
  msgid "is smaller or equal"
596
  msgstr ""
597
 
598
- #: lite/admin/class-ig-es-campaign-rules.php:662
599
- #: lite/admin/class-ig-es-campaign-rules.php:698
600
  msgid "match regex pattern"
601
  msgstr ""
602
 
603
- #: lite/admin/class-ig-es-campaign-rules.php:663
604
- #: lite/admin/class-ig-es-campaign-rules.php:699
605
  msgid "does not match regex pattern"
606
  msgstr ""
607
 
608
- #: lite/admin/class-ig-es-onboarding.php:171
609
  msgid "An error occured. Please try again later."
610
  msgstr ""
611
 
612
  #. translators: 1. Main list name. 2. Default list name.
613
- #: lite/admin/class-ig-es-onboarding.php:471
614
  msgid "Unable to create %1$s and %2$s list."
615
  msgstr ""
616
 
617
- #: lite/admin/class-ig-es-onboarding.php:611
618
  #: lite/includes/workflows/db/class-es-db-workflows.php:370
619
  #: lite/includes/workflows/triggers/class-es-trigger-user-registered.php:30
620
  msgid "User Registered"
621
  msgstr ""
622
 
623
- #: lite/admin/class-ig-es-onboarding.php:726
624
  msgid "Please accept terms & condition"
625
  msgstr ""
626
 
627
  #. translators: Active sidebar name.
628
- #: lite/admin/class-ig-es-onboarding.php:784
629
  msgid "Adding the form to \"%s\" sidebar, so you can show it on the site"
630
  msgstr ""
631
 
632
  #. translators: Active sidebar name.
633
- #: lite/admin/class-ig-es-onboarding.php:787
634
  msgid "Unable to add form widget to \"%s\" sidebar. Widget may already exists."
635
  msgstr ""
636
 
637
  #. translators: Active sidebar name.
638
- #: lite/admin/class-ig-es-onboarding.php:792
639
  msgid "Unable to add form widget to \"%s\" sidebar. No subscription form found."
640
  msgstr ""
641
 
642
- #: lite/admin/class-ig-es-onboarding.php:844
643
- #: lite/admin/class-ig-es-onboarding.php:845
644
  msgid "Welcome To Email Subscribers"
645
  msgstr ""
646
 
647
- #: lite/admin/class-ig-es-onboarding.php:1017
648
  msgid "Seems like your server is not setup correctly to send emails. Please confirm if you're getting any other emails from within WordPress"
649
  msgstr ""
650
 
651
- #: lite/admin/class-ig-es-onboarding.php:1143
652
  msgid "New Post Published - {{POSTTITLE}}"
653
  msgstr ""
654
 
@@ -666,7 +668,7 @@ msgid "Create"
666
  msgstr ""
667
 
668
  #: lite/admin/partials/dashboard.php:57
669
- #: lite/includes/classes/class-es-contacts-table.php:138
670
  #: lite/includes/classes/class-es-import-subscribers.php:391
671
  msgid "Import Contacts"
672
  msgstr ""
@@ -755,7 +757,7 @@ msgid " active contacts"
755
  msgstr ""
756
 
757
  #: lite/admin/partials/dashboard.php:169
758
- #: lite/includes/classes/class-es-contacts-table.php:325
759
  msgid "Last 60 days"
760
  msgstr ""
761
 
@@ -764,7 +766,7 @@ msgid " Avg Open Rate"
764
  msgstr ""
765
 
766
  #: lite/admin/partials/dashboard.php:201
767
- #: lite/includes/pro-features.php:1171
768
  msgid "Avg Click Rate"
769
  msgstr ""
770
 
@@ -807,58 +809,58 @@ msgstr ""
807
  msgid "Create self-expiring, automatic login links for WordPress. Give them to developers when they ask for admin access to your site."
808
  msgstr ""
809
 
810
- #: lite/admin/partials/help.php:82
811
  #: lite/includes/classes/class-es-info.php:19
812
  msgid "Help & Info"
813
  msgstr ""
814
 
815
- #: lite/admin/partials/help.php:103
816
  msgid "Database Migration"
817
  msgstr ""
818
 
819
  #. translators: 1. Starting strong tag 2. Closing strong tag
820
- #: lite/admin/partials/help.php:108
821
  msgid "If you found duplicate campaigns, lists, forms, reports after upgrading from Email Subscribers 3.5.x to 4.x and want to run the database migration again to fix this, please click the below %1$sRun the updater%2$s button."
822
  msgstr ""
823
 
824
  #. translators: 1. Starting strong tag 2. Closing strong tag
825
- #: lite/admin/partials/help.php:115
826
  msgid "Once you click on %1$sRun the updater%2$s button, it will run the migration process from 3.5.x once again. So, if you have created new campaigns, forms or lists after migration to 4.x earlier, you will lose those data. So, make sure you have a backup with you."
827
  msgstr ""
828
 
829
- #: lite/admin/partials/help.php:124
830
  #: lite/includes/notices/views/html-notice-update.php:23
831
  msgid "Run the updater"
832
  msgstr ""
833
 
834
- #: lite/admin/partials/help.php:132
835
  msgid "Get Help?"
836
  msgstr ""
837
 
838
- #: lite/admin/partials/help.php:142
839
  msgid "Contact US"
840
  msgstr ""
841
 
842
- #: lite/admin/partials/help.php:182
843
  msgid "Other awesome plugins from same author"
844
  msgstr ""
845
 
846
- #: lite/admin/partials/help.php:209
847
  #: lite/includes/classes/class-es-campaign-report.php:190
848
  #: lite/includes/classes/class-es-campaigns-table.php:630
849
  #: lite/includes/classes/class-es-export-subscribers.php:341
850
  #: lite/includes/classes/class-es-import-subscribers.php:666
851
- #: lite/includes/classes/class-es-import-subscribers.php:1180
852
- #: lite/includes/classes/class-es-reports-table.php:271
853
  #: lite/includes/workflows/class-es-workflows-table.php:338
854
  #: pro/classes/class-es-pro-sequence-report.php:301
855
  msgid "Status"
856
  msgstr ""
857
 
858
- #: lite/admin/partials/help.php:211
859
- #: lite/includes/class-es-common.php:390
860
- #: lite/includes/class-es-common.php:1746
861
- #: lite/includes/class-es-common.php:2176
862
  #: lite/includes/classes/class-es-campaigns-table.php:314
863
  #: lite/includes/workflows/admin/views/meta-box-save.php:28
864
  #: pro/classes/class-es-pro-reports-data.php:193
@@ -866,24 +868,24 @@ msgstr ""
866
  msgid "Active"
867
  msgstr ""
868
 
869
- #: lite/admin/partials/help.php:213
870
- #: lite/includes/class-es-common.php:391
871
- #: lite/includes/class-es-common.php:2181
872
  #: lite/includes/workflows/admin/views/meta-box-save.php:27
873
  #: pro/classes/class-es-pro-reports-data.php:198
874
  #: pro/classes/class-es-pro-sequence-report.php:239
875
  msgid "Inactive"
876
  msgstr ""
877
 
878
- #: lite/admin/partials/help.php:215
879
  msgid "Not Installed"
880
  msgstr ""
881
 
882
- #: lite/admin/partials/help.php:228
883
  msgid "Install"
884
  msgstr ""
885
 
886
- #: lite/admin/partials/help.php:231
887
  #: lite/includes/workflows/class-es-workflows-table.php:365
888
  msgid "Activate"
889
  msgstr ""
@@ -902,205 +904,205 @@ msgid ""
902
  "\t\t results quickly."
903
  msgstr ""
904
 
905
- #: lite/admin/partials/onboarding.php:54
906
  msgid "Essentials:"
907
  msgstr ""
908
 
909
- #: lite/admin/partials/onboarding.php:61
910
  msgid "\"From\" name for emails: "
911
  msgstr ""
912
 
913
- #: lite/admin/partials/onboarding.php:70
914
  msgid "\"From\" email: "
915
  msgstr ""
916
 
917
- #: lite/admin/partials/onboarding.php:81
918
  msgid "Email delivery testing:"
919
  msgstr ""
920
 
921
- #: lite/admin/partials/onboarding.php:86
922
  msgid ""
923
  "Add a couple of your own email addresses below. We will add\n"
924
  "\t\t them to your audience lists."
925
  msgstr ""
926
 
927
- #: lite/admin/partials/onboarding.php:112
928
  msgid "Your preferences:"
929
  msgstr ""
930
 
931
  #. translators: %s. Plugin name.
932
- #: lite/admin/partials/onboarding.php:147
933
  msgid "Help us to improve %s by opting in to share non-sensitive plugin usage data. No personal data is tracked or stored."
934
  msgstr ""
935
 
936
- #: lite/admin/partials/onboarding.php:167
937
  msgid ""
938
  "I want to send email notifications when new blog posts are\n"
939
  "\t\t published"
940
  msgstr ""
941
 
942
- #: lite/admin/partials/onboarding.php:186
943
  msgid ""
944
  "Enable double opt-in (people have to click a confirmation\n"
945
  "\t\t link in email before they're subscribed)"
946
  msgstr ""
947
 
948
- #: lite/admin/partials/onboarding.php:202
949
  msgid "Add GDPR consent in subscription forms"
950
  msgstr ""
951
 
952
- #: lite/admin/partials/onboarding.php:215
953
  msgid "Ok, set it up for me →"
954
  msgstr ""
955
 
956
- #: lite/admin/partials/onboarding.php:245
957
  msgid "STEP 2 of 3"
958
  msgstr ""
959
 
960
- #: lite/admin/partials/onboarding.php:249
961
  msgid "Hold on, personalizing for you..."
962
  msgstr ""
963
 
964
- #: lite/admin/partials/onboarding.php:254
965
  msgid ""
966
  "We'll create audience lists, campaigns and a subscription form.\n"
967
  "\t\t And then try to send a test email to make sure everything works."
968
  msgstr ""
969
 
970
  #. translators: 1: Main List 2: Test List
971
- #: lite/admin/partials/onboarding.php:267
972
  msgid "Creating audience lists - %1$s &amp; %2$s"
973
  msgstr ""
974
 
975
- #: lite/admin/partials/onboarding.php:281
976
  msgid "Subscribing you and "
977
  msgstr ""
978
 
979
- #: lite/admin/partials/onboarding.php:283
980
  msgid " to these lists"
981
  msgstr ""
982
 
983
- #: lite/admin/partials/onboarding.php:295
984
  msgid "Creating a campaign - newsletter broadcast test"
985
  msgstr ""
986
 
987
- #: lite/admin/partials/onboarding.php:307
988
  msgid "Creating a campaign - new post notification test"
989
  msgstr ""
990
 
991
- #: lite/admin/partials/onboarding.php:319
992
  msgid "Creating a subscription opt-in form for the Main list"
993
  msgstr ""
994
 
995
- #: lite/admin/partials/onboarding.php:332
996
  msgid ""
997
  "Adding the form to an active sidebar, so you can show it on\n"
998
  "\t\t the site"
999
  msgstr ""
1000
 
1001
- #: lite/admin/partials/onboarding.php:347
1002
  msgid "Testing email delivery..."
1003
  msgstr ""
1004
 
1005
- #: lite/admin/partials/onboarding.php:357
1006
  msgid "Queuing up campaign - newsletter broadcast test"
1007
  msgstr ""
1008
 
1009
- #: lite/admin/partials/onboarding.php:367
1010
  msgid "Dispatching emails from your server"
1011
  msgstr ""
1012
 
1013
- #: lite/admin/partials/onboarding.php:378
1014
  msgid "Waiting for test email to arrive on destination server"
1015
  msgstr ""
1016
 
1017
- #: lite/admin/partials/onboarding.php:389
1018
  msgid "Excellent! Email delivery setup is working well!"
1019
  msgstr ""
1020
 
1021
- #: lite/admin/partials/onboarding.php:402
1022
  msgid "Continue anyway →"
1023
  msgstr ""
1024
 
1025
- #: lite/admin/partials/onboarding.php:404
1026
  msgid "All good, let's finish up →"
1027
  msgstr ""
1028
 
1029
- #: lite/admin/partials/onboarding.php:439
1030
  msgid "STEP 3 of 3"
1031
  msgstr ""
1032
 
1033
- #: lite/admin/partials/onboarding.php:443
1034
  msgid "Done! Now speed up your success!"
1035
  msgstr ""
1036
 
1037
- #: lite/admin/partials/onboarding.php:450
1038
  msgid "Setup is complete. Couple of things to support you..."
1039
  msgstr ""
1040
 
1041
- #: lite/admin/partials/onboarding.php:455
1042
  msgid "Free course: WordPress Email Marketing Masterclass 2021"
1043
  msgstr ""
1044
 
1045
- #: lite/admin/partials/onboarding.php:459
1046
  msgid ""
1047
  "How to build your list, make sure your email reach your\n"
1048
  "\t\t\t\t audience and influence your audience."
1049
  msgstr ""
1050
 
1051
- #: lite/admin/partials/onboarding.php:488
1052
  msgid "Premium features for free:"
1053
  msgstr ""
1054
 
1055
- #: lite/admin/partials/onboarding.php:511
1056
  msgid "Yes, start the trial"
1057
  msgstr ""
1058
 
1059
- #: lite/admin/partials/onboarding.php:521
1060
  msgid "Recommended next steps:"
1061
  msgstr ""
1062
 
1063
- #: lite/admin/partials/onboarding.php:524
1064
  msgid "Review \"Settings\" and make adjustments if needed"
1065
  msgstr ""
1066
 
1067
- #: lite/admin/partials/onboarding.php:525
1068
  msgid "Import your contacts, create new campaigns and test"
1069
  msgstr ""
1070
 
1071
- #: lite/admin/partials/onboarding.php:528
1072
  #: pro/workflows/triggers/class-es-trigger-wc-product-review-approved.php:25
1073
  msgid "Review"
1074
  msgstr ""
1075
 
1076
- #: lite/admin/partials/onboarding.php:533
1077
  msgid "documentation"
1078
  msgstr ""
1079
 
1080
- #: lite/admin/partials/onboarding.php:535
1081
  msgid "if you need any help"
1082
  msgstr ""
1083
 
1084
- #: lite/admin/partials/onboarding.php:548
1085
  msgid "Complete setup &amp; take me to \"Dashboard\" "
1086
  msgstr ""
1087
 
1088
- #: lite/admin/partials/onboarding.php:589
1089
  msgid "Email sending did not work"
1090
  msgstr ""
1091
 
1092
- #: lite/admin/partials/onboarding.php:594
1093
  msgid "Here's the error we encountered:"
1094
  msgstr ""
1095
 
1096
- #: lite/admin/partials/onboarding.php:605
1097
  msgid ""
1098
  "We recommend you solve this problem quickly after completing\n"
1099
  "\t\t\t\t\t the setup. Do make sure emails are getting delivered before\n"
1100
  "\t\t\t\t\t you send any real campaigns."
1101
  msgstr ""
1102
 
1103
- #: lite/admin/partials/onboarding.php:621
1104
  msgid " Understood, continue for now →"
1105
  msgstr ""
1106
 
@@ -1142,234 +1144,234 @@ msgid "Set thumbnail"
1142
  msgstr ""
1143
 
1144
  #. translators: %s: Cron URL
1145
- #: lite/includes/class-email-subscribers.php:370
1146
  msgid "WordPress Cron is disabled on your site. Email notifications from Email Subscribers plugin will not be sent automatically. <a href=\"%s\" target=\"_blank\" >Here's how you can enable it.</a>"
1147
  msgstr ""
1148
 
1149
  #. translators: %s: Link to Cpanel URL
1150
- #: lite/includes/class-email-subscribers.php:372
1151
  msgid "Or schedule Cron in <a href=\"%s\" target=\"_blank\">cPanel</a>"
1152
  msgstr ""
1153
 
1154
  #. translators: %s: ES Pro URL
1155
- #: lite/includes/class-email-subscribers.php:374
1156
  msgid "Or use <strong><a href=\"%s\" target=\"_blank\">Email Subscribers Pro</a></strong> for automatic Cron support"
1157
  msgstr ""
1158
 
1159
- #: lite/includes/class-email-subscribers.php:375
1160
  msgid "OK, I Got it!"
1161
  msgstr ""
1162
 
1163
  #. translators: 1: Error message 2: File name 3: Line number
1164
- #: lite/includes/class-email-subscribers.php:1295
1165
  msgid "%1$s in %2$s on line %3$s"
1166
  msgstr ""
1167
 
1168
- #: lite/includes/class-email-subscribers.php:1558
1169
  msgid "Icegram WC"
1170
  msgstr ""
1171
 
1172
  #. translators: %1$s - constant that was used
1173
- #: lite/includes/class-email-subscribers.php:1967
1174
  msgid "Value was set using constant %1$s"
1175
  msgstr ""
1176
 
1177
- #: lite/includes/class-es-common.php:191
1178
- #: lite/includes/classes/class-es-contacts-table.php:348
1179
  #: lite/includes/classes/class-es-import-subscribers.php:839
1180
- #: lite/includes/classes/class-es-import-subscribers.php:1187
1181
  #: lite/includes/classes/class-es-lists-table.php:573
1182
  msgid "Unconfirmed"
1183
  msgstr ""
1184
 
1185
- #: lite/includes/class-es-common.php:215
1186
  #: lite/includes/classes/class-es-import-subscribers.php:236
1187
  msgid "Select Status"
1188
  msgstr ""
1189
 
1190
- #: lite/includes/class-es-common.php:349
1191
  msgid "Select Template"
1192
  msgstr ""
1193
 
1194
- #: lite/includes/class-es-common.php:459
1195
  msgid "Select Categories"
1196
  msgstr ""
1197
 
1198
- #: lite/includes/class-es-common.php:472
1199
  msgid "All Categories (Also include all categories which will create later)"
1200
  msgstr ""
1201
 
1202
- #: lite/includes/class-es-common.php:476
1203
  msgid "None (Don't include post from any category)"
1204
  msgstr ""
1205
 
1206
- #: lite/includes/class-es-common.php:509
1207
  msgid "No Custom Post Types Available"
1208
  msgstr ""
1209
 
1210
- #: lite/includes/class-es-common.php:525
1211
  msgid "Single Opt-In"
1212
  msgstr ""
1213
 
1214
- #: lite/includes/class-es-common.php:526
1215
  msgid "Double Opt-In"
1216
  msgstr ""
1217
 
1218
- #: lite/includes/class-es-common.php:541
1219
  #: pro/pro-class-post-digest.php:149
1220
  msgid "Monday"
1221
  msgstr ""
1222
 
1223
- #: lite/includes/class-es-common.php:542
1224
  #: pro/pro-class-post-digest.php:150
1225
  msgid "Tuesday"
1226
  msgstr ""
1227
 
1228
- #: lite/includes/class-es-common.php:543
1229
  #: pro/pro-class-post-digest.php:151
1230
  msgid "Wednesday"
1231
  msgstr ""
1232
 
1233
- #: lite/includes/class-es-common.php:544
1234
  #: pro/pro-class-post-digest.php:152
1235
  msgid "Thursday"
1236
  msgstr ""
1237
 
1238
- #: lite/includes/class-es-common.php:545
1239
  #: pro/pro-class-post-digest.php:153
1240
  msgid "Friday"
1241
  msgstr ""
1242
 
1243
- #: lite/includes/class-es-common.php:546
1244
  #: pro/pro-class-post-digest.php:154
1245
  msgid "Saturday"
1246
  msgstr ""
1247
 
1248
- #: lite/includes/class-es-common.php:547
1249
  #: pro/pro-class-post-digest.php:148
1250
  msgid "Sunday"
1251
  msgstr ""
1252
 
1253
- #: lite/includes/class-es-common.php:584
1254
  msgid "Full Size"
1255
  msgstr ""
1256
 
1257
- #: lite/includes/class-es-common.php:585
1258
  msgid "Medium Size"
1259
  msgstr ""
1260
 
1261
- #: lite/includes/class-es-common.php:586
1262
  #: lite/includes/classes/class-es-templates-table.php:263
1263
  msgid "Thumbnail"
1264
  msgstr ""
1265
 
1266
- #: lite/includes/class-es-common.php:1506
1267
  msgid "Top 10 Tips on How to Build an Email List"
1268
  msgstr ""
1269
 
1270
- #: lite/includes/class-es-common.php:1510
1271
  #: pro/templates/email/es-admin-subscription-summary.php:174
1272
  msgid "Why are Your Email Unsubscribes Increasing and How to Fix Them?"
1273
  msgstr ""
1274
 
1275
- #: lite/includes/class-es-common.php:1514
1276
  msgid "Balance Email Marketing and Social Media Marketing"
1277
  msgstr ""
1278
 
1279
- #: lite/includes/class-es-common.php:1518
1280
  msgid "Use social proof to grow blog traffic through email"
1281
  msgstr ""
1282
 
1283
- #: lite/includes/class-es-common.php:1522
1284
  msgid "5 Simple Tricks to Improve Email Marketing Campaign Results"
1285
  msgstr ""
1286
 
1287
- #: lite/includes/class-es-common.php:1531
1288
- #: lite/includes/pro-features.php:144
1289
  msgid "Email Subscribers PRO"
1290
  msgstr ""
1291
 
1292
- #: lite/includes/class-es-common.php:1533
1293
  msgid "Lifetime"
1294
  msgstr ""
1295
 
1296
- #: lite/includes/class-es-common.php:1537
1297
  msgid "<b>Email Subscribers Secret Club</b>"
1298
  msgstr ""
1299
 
1300
- #: lite/includes/class-es-common.php:1539
1301
- #: lite/includes/feedback.php:124
1302
  msgid "Join Now"
1303
  msgstr ""
1304
 
1305
- #: lite/includes/class-es-common.php:1714
1306
  msgid "All Types"
1307
  msgstr ""
1308
 
1309
- #: lite/includes/class-es-common.php:1742
1310
  #: lite/includes/classes/class-es-campaigns-table.php:568
1311
  msgid "Draft"
1312
  msgstr ""
1313
 
1314
- #: lite/includes/class-es-common.php:1743
1315
- #: lite/includes/class-es-common.php:2167
1316
  #: lite/includes/classes/class-es-campaign-report.php:237
1317
  #: lite/includes/classes/class-es-campaigns-table.php:549
1318
  #: lite/includes/classes/class-es-campaigns-table.php:587
1319
- #: lite/includes/classes/class-es-reports-table.php:197
1320
- #: lite/includes/classes/class-es-reports-table.php:557
1321
  #: pro/classes/class-es-pro-reports-data.php:186
1322
  msgid "Sending"
1323
  msgstr ""
1324
 
1325
- #: lite/includes/class-es-common.php:1744
1326
  #: lite/includes/classes/class-es-campaigns-table.php:315
1327
  #: lite/includes/classes/class-es-campaigns-table.php:542
1328
  #: lite/includes/classes/class-es-campaigns-table.php:578
1329
- #: lite/includes/classes/class-es-reports-table.php:207
1330
  #: lite/includes/workflows/admin/views/meta-box-timing.php:36
1331
  msgid "Scheduled"
1332
  msgstr ""
1333
 
1334
- #: lite/includes/class-es-common.php:1745
1335
- #: lite/includes/class-es-common.php:2147
1336
  #: lite/includes/classes/class-es-campaign-report.php:221
1337
  #: lite/includes/classes/class-es-campaigns-table.php:556
1338
  #: lite/includes/classes/class-es-campaigns-table.php:605
1339
  #: lite/includes/classes/class-es-reports-table.php:191
1340
- #: lite/includes/pro-features.php:1116
1341
- #: lite/includes/pro-features.php:1163
1342
  #: pro/classes/class-es-pro-reports-data.php:170
1343
  #: pro/classes/class-es-pro-reports-data.php:270
1344
  msgid "Sent"
1345
  msgstr ""
1346
 
1347
- #: lite/includes/class-es-common.php:1770
1348
  #: lite/includes/classes/class-es-campaigns-table.php:690
1349
- #: lite/includes/classes/class-es-contacts-table.php:1138
1350
  msgid "All Statuses"
1351
  msgstr ""
1352
 
1353
- #: lite/includes/class-es-common.php:1982
1354
  msgid "Upgrade"
1355
  msgstr ""
1356
 
1357
- #: lite/includes/class-es-common.php:2016
1358
- #: lite/includes/classes/class-es-reports-table.php:559
1359
  #: pro/classes/class-es-pro-reports-data.php:878
1360
  msgid "All Status"
1361
  msgstr ""
1362
 
1363
- #: lite/includes/class-es-common.php:2157
1364
  #: lite/includes/classes/class-es-campaign-report.php:229
1365
- #: lite/includes/classes/class-es-reports-table.php:556
1366
  #: pro/classes/class-es-pro-reports-data.php:178
1367
  #: pro/partials/es-dashboard.php:60
1368
  msgid "In Queue"
1369
  msgstr ""
1370
 
1371
- #: lite/includes/class-es-install.php:832
1372
- #: lite/includes/upgrade/es-update-functions.php:750
1373
  msgid "Your subscription was successful! Kindly check your mailbox and confirm your subscription. If you don't see the email within a few minutes, check the spam/junk folder."
1374
  msgstr ""
1375
 
@@ -1400,10 +1402,11 @@ msgstr ""
1400
  #: lite/includes/classes/class-es-admin-settings.php:202
1401
  #: lite/includes/classes/class-es-admin-settings.php:205
1402
  #: lite/includes/classes/class-es-campaigns-table.php:625
1403
- #: lite/includes/classes/class-es-contacts-table.php:1068
1404
  #: lite/includes/classes/class-es-forms-table.php:410
1405
- #: lite/includes/classes/class-es-forms-table.php:900
1406
  #: lite/includes/classes/class-es-lists-table.php:569
 
1407
  #: lite/public/partials/class-es-shortcode.php:170
1408
  msgid "Name"
1409
  msgstr ""
@@ -1572,7 +1575,7 @@ msgstr ""
1572
  #: lite/includes/classes/class-es-admin-settings.php:453
1573
  #: lite/includes/classes/class-es-admin-settings.php:491
1574
  #: lite/includes/classes/class-es-newsletters.php:355
1575
- #: lite/includes/classes/class-es-reports-table.php:269
1576
  #: pro/classes/class-es-pro-sequence-report.php:299
1577
  msgid "Subject"
1578
  msgstr ""
@@ -1639,7 +1642,7 @@ msgid "Notify admin(s) everytime a campaign is sent."
1639
  msgstr ""
1640
 
1641
  #: lite/includes/classes/class-es-admin-settings.php:489
1642
- #: lite/includes/classes/class-es-mailer.php:363
1643
  msgid "Campaign Sent!"
1644
  msgstr ""
1645
 
@@ -1726,7 +1729,7 @@ msgstr ""
1726
  msgid "Seeing spam signups from particular domains? Enter domains names (one per line) that you want to block here."
1727
  msgstr ""
1728
 
1729
- #: lite/includes/classes/class-es-admin-settings.php:847
1730
  msgid "Save Settings"
1731
  msgstr ""
1732
 
@@ -1776,7 +1779,7 @@ msgstr ""
1776
  #: lite/includes/classes/class-es-campaigns-table.php:448
1777
  #: lite/includes/classes/class-es-campaigns-table.php:479
1778
  #: lite/includes/classes/class-es-reports-table.php:16
1779
- #: lite/includes/pro-features.php:1108
1780
  #: pro/classes/class-es-pro-reports-data.php:154
1781
  #: pro/classes/class-es-pro-sequence-report.php:20
1782
  msgid "Report"
@@ -1802,14 +1805,14 @@ msgid "Viewed Date"
1802
  msgstr ""
1803
 
1804
  #: lite/includes/classes/class-es-campaign-report.php:245
1805
- #: lite/includes/classes/class-es-contacts-table.php:356
1806
- #: lite/includes/pro-features.php:1147
1807
  #: pro/classes/class-es-pro-reports-data.php:247
1808
  #: pro/classes/class-es-pro-reports-data.php:875
1809
  msgid "Opened"
1810
  msgstr ""
1811
 
1812
- #: lite/includes/classes/class-es-campaign-report.php:459
1813
  msgid "Campaign Analytics"
1814
  msgstr ""
1815
 
@@ -1862,7 +1865,7 @@ msgstr ""
1862
 
1863
  #: lite/includes/classes/class-es-campaigns-table.php:317
1864
  #: lite/includes/classes/class-es-campaigns-table.php:596
1865
- #: lite/includes/classes/class-es-reports-table.php:202
1866
  msgid "Paused"
1867
  msgstr ""
1868
 
@@ -1881,23 +1884,23 @@ msgstr ""
1881
 
1882
  #: lite/includes/classes/class-es-campaigns-table.php:438
1883
  #: lite/includes/classes/class-es-campaigns-table.php:465
1884
- #: lite/includes/classes/class-es-contacts-table.php:1030
1885
- #: lite/includes/classes/class-es-forms-table.php:883
1886
  #: lite/includes/classes/class-es-lists-table.php:547
1887
  #: lite/includes/workflows/admin/views/action.php:28
1888
  #: lite/includes/workflows/class-es-workflows-table.php:305
1889
  msgid "Edit"
1890
  msgstr ""
1891
 
1892
- #: lite/includes/classes/class-es-campaigns-table.php:490
1893
- #: lite/includes/classes/class-es-contacts-table.php:1032
1894
- #: lite/includes/classes/class-es-contacts-table.php:1104
1895
- #: lite/includes/classes/class-es-forms-table.php:885
1896
- #: lite/includes/classes/class-es-forms-table.php:931
2
  # This file is distributed under the same license as the Email Subscribers & Newsletters plugin.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Email Subscribers & Newsletters 4.8.2\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/email-subscribers\n"
7
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
8
  "Language-Team: LANGUAGE <LL@li.org>\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
+ "POT-Creation-Date: 2021-09-21T19:43:26+02:00\n"
13
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
  "X-Generator: WP-CLI 2.4.0\n"
15
  "X-Domain: email-subscribers\n"
29
 
30
  #. Author of the plugin
31
  #: lite/admin/partials/help.php:28
32
+ #: lite/includes/class-email-subscribers.php:1529
33
  msgid "Icegram"
34
  msgstr ""
35
 
36
  #. translators: %s: PHP version
37
+ #: email-subscribers.php:50
38
  msgid "Email Subscribers requires PHP version %s+, plugin is currently NOT RUNNING."
39
  msgstr ""
40
 
41
  #. translators: %s: Link to Email Subscribers Premium upgrade
42
+ #: email-subscribers.php:117
43
  msgid "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."
44
  msgstr ""
45
 
46
+ #: email-subscribers.php:118
47
  msgid "Email Subscribers Premium"
48
  msgstr ""
49
 
50
+ #: email-subscribers.php:229
51
  msgid "Email Subscribers requires WooCommerce to be installed and active, plugin is currently NOT RUNNING."
52
  msgstr ""
53
 
54
+ #: lite/admin/class-email-subscribers-admin.php:166
55
  msgid "An error has occured. Please try again later."
56
  msgstr ""
57
 
58
+ #: lite/admin/class-email-subscribers-admin.php:167
59
  msgid "Broadcast saved successfully."
60
  msgstr ""
61
 
62
+ #: lite/admin/class-email-subscribers-admin.php:168
63
  msgid "An error has occured while saving the broadcast. Please try again later."
64
  msgstr ""
65
 
66
+ #: lite/admin/class-email-subscribers-admin.php:169
67
  msgid "Please add a broadcast subject before saving."
68
  msgstr ""
69
 
70
+ #: lite/admin/class-email-subscribers-admin.php:170
71
  #: pro/pro-class-email-subscribers.php:504
72
  msgid "Please add email body."
73
  msgstr ""
74
 
75
+ #: lite/admin/class-email-subscribers-admin.php:171
76
  msgid "Do you really like to remove all conditions?"
77
  msgstr ""
78
 
79
+ #: lite/admin/class-email-subscribers-admin.php:174
80
  msgid "Please select a trigger before saving the workflow."
81
  msgstr ""
82
 
83
+ #: lite/admin/class-email-subscribers-admin.php:175
84
  msgid "Please add some actions before saving the workflow."
85
  msgstr ""
86
 
87
+ #: lite/admin/class-email-subscribers-admin.php:176
88
  msgid "Please select an action that this workflow should perform before saving the workflow."
89
  msgstr ""
90
 
91
+ #: lite/admin/class-email-subscribers-admin.php:177
92
  msgid "Changing the trigger will remove existing actions. Do you want to proceed anyway?."
93
  msgstr ""
94
 
95
+ #: lite/admin/class-email-subscribers-admin.php:178
96
  msgid "Copied!"
97
  msgstr ""
98
 
99
+ #: lite/admin/class-email-subscribers-admin.php:179
100
  msgid "Are you sure?"
101
  msgstr ""
102
 
103
+ #: lite/admin/class-email-subscribers-admin.php:182
104
  msgid "Please select the status for the importing contacts!"
105
  msgstr ""
106
 
107
+ #: lite/admin/class-email-subscribers-admin.php:183
108
  msgid "Please select a list for importing contacts!"
109
  msgstr ""
110
 
111
+ #: lite/admin/class-email-subscribers-admin.php:184
112
  msgid "Please select the email address column!"
113
  msgstr ""
114
 
115
+ #: lite/admin/class-email-subscribers-admin.php:185
116
  msgid "Preparing Data"
117
  msgstr ""
118
 
119
  #. translators: %s: Upload progress
120
+ #: lite/admin/class-email-subscribers-admin.php:187
121
  msgid "Uploading...%s"
122
  msgstr ""
123
 
124
  #. translators: %s: Import progress
125
+ #: lite/admin/class-email-subscribers-admin.php:189
126
  msgid "Importing contacts...%s"
127
  msgstr ""
128
 
129
  #. translators: %s: Import failed svg icon
130
+ #: lite/admin/class-email-subscribers-admin.php:191
131
  msgid "Import failed! %s"
132
  msgstr ""
133
 
134
+ #: lite/admin/class-email-subscribers-admin.php:192
135
  msgid "Please do not close this window until it completes..."
136
  msgstr ""
137
 
138
+ #: lite/admin/class-email-subscribers-admin.php:193
139
  msgid "Preparing Import..."
140
  msgstr ""
141
 
142
  #. translators: 1. Imported contacts count 2. Total contacts count 3. Failed to import count 4. Memory usage
143
+ #: lite/admin/class-email-subscribers-admin.php:195
144
  msgid "Currently %1$s of %2$s imported with %3$s errors. %4$s %5$s memory usage"
145
  msgstr ""
146
 
147
  #. translators: 1 Duplicate found email message
148
+ #: lite/admin/class-email-subscribers-admin.php:197
149
  msgid "%1$s duplicate emails found."
150
  msgstr ""
151
 
152
  #. translators: %s: Time left in minutes
153
+ #: lite/admin/class-email-subscribers-admin.php:199
154
  msgid "Estimate time left: %s minutes"
155
  msgstr ""
156
 
157
  #. translators: %s: Next attempt delaly time
158
+ #: lite/admin/class-email-subscribers-admin.php:201
159
  msgid "Continues in %s seconds"
160
  msgstr ""
161
 
162
+ #: lite/admin/class-email-subscribers-admin.php:202
163
  msgid "There was a problem during importing contacts. Please check the error logs for more information!"
164
  msgstr ""
165
 
166
+ #: lite/admin/class-email-subscribers-admin.php:203
167
  msgid "Do you really like to import these contacts?"
168
  msgstr ""
169
 
170
  #. translators: %s: Process complete svg icon
171
+ #: lite/admin/class-email-subscribers-admin.php:205
172
  msgid "Import complete! %s"
173
  msgstr ""
174
 
175
+ #: lite/admin/class-email-subscribers-admin.php:206
176
  msgid "You are currently importing subscribers! If you leave the page all pending subscribers don't get imported!"
177
  msgstr ""
178
 
179
+ #: lite/admin/class-email-subscribers-admin.php:207
180
  msgid "API is valid. Fetching lists..."
181
  msgstr ""
182
 
183
+ #: lite/admin/class-email-subscribers-admin.php:208
184
  msgid "Fetching contacts from MailChimp...Please do not close this window"
185
  msgstr ""
186
 
187
+ #: lite/admin/class-email-subscribers-admin.php:286
188
  #: lite/admin/partials/dashboard.php:100
189
  msgid "Dashboard"
190
  msgstr ""
191
 
192
+ #: lite/admin/class-email-subscribers-admin.php:291
193
  #: lite/admin/partials/dashboard.php:107
194
+ #: lite/includes/classes/class-es-contacts-table.php:214
195
+ #: lite/includes/pro-features.php:160
196
  #: starter/starter-class-email-subscribers.php:646
197
  msgid "Audience"
198
  msgstr ""
199
 
200
+ #: lite/admin/class-email-subscribers-admin.php:295
201
  #: lite/includes/classes/class-es-forms-table.php:459
202
  #: lite/includes/classes/class-es-lists-table.php:34
203
  #: lite/includes/classes/class-es-lists-table.php:88
204
  msgid "Lists"
205
  msgstr ""
206
 
207
+ #: lite/admin/class-email-subscribers-admin.php:301
208
  #: lite/includes/classes/class-es-form-widget.php:70
209
  #: lite/includes/classes/class-es-forms-table.php:39
210
  #: lite/includes/classes/class-es-forms-table.php:40
211
  #: lite/includes/classes/class-es-forms-table.php:93
212
+ #: lite/includes/pro-features.php:161
213
  #: starter/starter-class-email-subscribers.php:647
214
  msgid "Forms"
215
  msgstr ""
216
 
217
+ #: lite/admin/class-email-subscribers-admin.php:307
218
  #: lite/includes/classes/class-es-campaigns-table.php:130
219
  #: lite/includes/classes/class-es-newsletters.php:239
220
  #: lite/includes/classes/class-es-newsletters.php:245
221
+ #: lite/includes/pro-features.php:162
222
  #: pro/partials/es-dashboard.php:8
223
  #: starter/starter-class-email-subscribers.php:648
224
  msgid "Campaigns"
225
  msgstr ""
226
 
227
+ #: lite/admin/class-email-subscribers-admin.php:311
228
  msgid "Post Notifications"
229
  msgstr ""
230
 
231
+ #: lite/admin/class-email-subscribers-admin.php:313
232
  #: lite/includes/classes/class-es-campaigns-table.php:362
233
  #: lite/includes/classes/class-es-newsletters.php:254
234
+ #: lite/includes/classes/class-es-reports-data.php:360
235
+ #: lite/includes/classes/class-es-reports-table.php:161
236
  #: lite/includes/classes/class-es-templates-table.php:282
237
+ #: lite/includes/pro-features.php:1146
238
  #: lite/public/class-email-subscribers-public.php:472
239
  #: pro/classes/class-es-pro-reports-data.php:77
240
  msgid "Broadcast"
241
  msgstr ""
242
 
243
+ #: lite/admin/class-email-subscribers-admin.php:314
244
  #: lite/includes/classes/class-es-newsletters.php:430
245
+ #: lite/includes/classes/class-es-reports-table.php:532
246
  msgid "Template Preview"
247
  msgstr ""
248
 
249
+ #: lite/admin/class-email-subscribers-admin.php:321
250
+ #: lite/includes/pro-features.php:165
251
  #: lite/includes/workflows/admin/class-es-workflow-admin-edit.php:229
252
  #: lite/includes/workflows/class-es-workflows-table.php:53
253
  #: lite/includes/workflows/class-es-workflows-table.php:169
255
  msgid "Workflows"
256
  msgstr ""
257
 
258
+ #: lite/admin/class-email-subscribers-admin.php:330
259
  #: lite/admin/partials/dashboard.php:238
260
  #: lite/includes/classes/class-es-campaign-report.php:17
261
  #: lite/includes/classes/class-es-reports-table.php:17
262
+ #: lite/includes/classes/class-es-reports-table.php:55
263
+ #: lite/includes/classes/class-es-reports-table.php:112
264
+ #: lite/includes/pro-features.php:163
265
  #: pro/classes/class-es-pro-sequence-report.php:21
266
  #: pro/classes/class-es-pro-sequence-report.php:44
267
  #: pro/classes/class-es-pro-sequence-report.php:77
269
  msgid "Reports"
270
  msgstr ""
271
 
272
+ #: lite/admin/class-email-subscribers-admin.php:334
273
  #: lite/admin/partials/dashboard.php:246
274
  #: lite/includes/classes/class-es-admin-settings.php:131
275
  msgid "Settings"
276
  msgstr ""
277
 
278
+ #: lite/admin/class-email-subscribers-admin.php:339
279
  msgid "Go To Icegram"
280
  msgstr ""
281
 
282
  #. translators: 1. WordPress URL 2. Email Subscribers version 3. Icegram site URL
283
+ #: lite/admin/class-email-subscribers-admin.php:889
284
  msgid "<span id=\"footer-thankyou\">Thank you for creating with <a href=\"%1$s\" target=\"_blank\">WordPress</a> | Email Subscribers <b>%2$s</b>. Developed by team <a href=\"%3$s\" target=\"_blank\">Icegram</a></span>"
285
  msgstr ""
286
 
287
+ #: lite/admin/class-email-subscribers-admin.php:917
288
  msgid "Something went wrong"
289
  msgstr ""
290
 
291
+ #: lite/admin/class-email-subscribers-admin.php:1291
292
  #: lite/includes/class-email-subscribers-activator.php:61
293
+ #: lite/includes/class-email-subscribers.php:1526
294
  #: lite/includes/classes/class-es-form-widget.php:11
295
  #: lite/includes/classes/class-es-old-widget.php:13
296
  #: lite/includes/classes/class-es-old-widget.php:15
297
  #: lite/includes/classes/class-es-widget.php:11
298
+ #: lite/includes/compatibilities/elementor/actions/class-es-ig-form-action.php:39
299
  msgid "Email Subscribers"
300
  msgstr ""
301
 
302
+ #: lite/admin/class-email-subscribers-admin.php:1333
303
  msgid "Last 30 days"
304
  msgstr ""
305
 
306
+ #: lite/admin/class-email-subscribers-admin.php:1342
307
+ #: lite/includes/class-es-common.php:191
308
+ #: lite/includes/classes/class-es-contacts-table.php:327
309
  #: lite/includes/classes/class-es-import-subscribers.php:837
310
+ #: lite/includes/classes/class-es-import-subscribers.php:1183
311
  #: lite/includes/classes/class-es-lists-table.php:571
312
  msgid "Subscribed"
313
  msgstr ""
314
 
315
+ #: lite/admin/class-email-subscribers-admin.php:1350
316
+ #: lite/includes/class-es-common.php:193
317
+ #: lite/includes/classes/class-es-contacts-table.php:335
318
  #: lite/includes/classes/class-es-import-subscribers.php:838
319
+ #: lite/includes/classes/class-es-import-subscribers.php:1184
320
  #: lite/includes/classes/class-es-lists-table.php:572
321
  #: pro/classes/class-es-pro-reports-data.php:283
322
  msgid "Unsubscribed"
323
  msgstr ""
324
 
325
+ #: lite/admin/class-email-subscribers-admin.php:1358
326
+ #: lite/includes/pro-features.php:1178
327
  msgid "Avg Open Rate"
328
  msgstr ""
329
 
330
+ #: lite/admin/class-email-subscribers-admin.php:1366
331
  #: lite/admin/partials/dashboard.php:193
332
  msgid "Messages Sent"
333
  msgstr ""
334
 
335
+ #: lite/admin/class-email-subscribers-admin.php:1377
336
  msgid "Last Campaign"
337
  msgstr ""
338
 
339
+ #: lite/admin/class-email-subscribers-admin.php:1413
340
  msgid "Sent to"
341
  msgstr ""
342
 
343
+ #: lite/admin/class-email-subscribers-admin.php:1425
344
  #: lite/admin/partials/dashboard.php:177
345
+ #: lite/includes/pro-features.php:1258
346
+ #: lite/includes/pro-features.php:1296
347
  #: pro/classes/class-es-pro-reports-data.php:321
348
  #: pro/classes/class-es-pro-reports-data.php:444
349
  #: pro/classes/class-es-pro-reports-data.php:677
352
  msgid "Opens"
353
  msgstr ""
354
 
355
+ #: lite/admin/class-email-subscribers-admin.php:1439
356
  msgid "No campaigns sent yet"
357
  msgstr ""
358
 
359
+ #: lite/admin/class-email-subscribers-admin.php:1447
360
  msgid "Latest Blog Posts from Icegram"
361
  msgstr ""
362
 
363
+ #: lite/admin/class-ig-es-campaign-rules.php:169
364
  msgid "Recipients"
365
  msgstr ""
366
 
367
+ #: lite/admin/class-ig-es-campaign-rules.php:179
368
  msgid "Add recipients"
369
  msgstr ""
370
 
371
+ #: lite/admin/class-ig-es-campaign-rules.php:182
372
+ #: lite/admin/class-ig-es-campaign-rules.php:254
373
+ #: lite/admin/class-ig-es-campaign-rules.php:256
374
+ #: lite/admin/class-ig-es-campaign-rules.php:521
375
+ #: lite/admin/class-ig-es-campaign-rules.php:526
376
+ #: lite/admin/class-ig-es-campaign-rules.php:532
377
+ #: lite/admin/class-ig-es-campaign-rules.php:566
378
  msgid "or"
379
  msgstr ""
380
 
381
+ #: lite/admin/class-ig-es-campaign-rules.php:184
382
  msgid "remove all"
383
  msgstr ""
384
 
385
+ #: lite/admin/class-ig-es-campaign-rules.php:204
386
  msgid "Campaign Rules"
387
  msgstr ""
388
 
389
+ #: lite/admin/class-ig-es-campaign-rules.php:208
390
  msgid "Loading..."
391
  msgstr ""
392
 
393
+ #: lite/admin/class-ig-es-campaign-rules.php:209
394
  msgid "Save Rules"
395
  msgstr ""
396
 
397
+ #: lite/admin/class-ig-es-campaign-rules.php:211
398
  msgid "Close panel"
399
  msgstr ""
400
 
401
+ #: lite/admin/class-ig-es-campaign-rules.php:225
402
  msgid "Total recipients"
403
  msgstr ""
404
 
405
+ #: lite/admin/class-ig-es-campaign-rules.php:245
406
+ #: lite/admin/class-ig-es-campaign-rules.php:416
407
+ #: lite/admin/class-ig-es-campaign-rules.php:563
408
  msgid "and"
409
  msgstr ""
410
 
411
+ #: lite/admin/class-ig-es-campaign-rules.php:254
412
+ #: lite/admin/class-ig-es-campaign-rules.php:379
413
  msgid "Add Condition"
414
  msgstr ""
415
 
416
+ #: lite/admin/class-ig-es-campaign-rules.php:257
417
  msgid "remove condition"
418
  msgstr ""
419
 
420
+ #: lite/admin/class-ig-es-campaign-rules.php:339
421
+ #: lite/admin/class-ig-es-campaign-rules.php:724
422
  msgid "Any campaign"
423
  msgstr ""
424
 
425
+ #: lite/admin/class-ig-es-campaign-rules.php:345
426
+ #: lite/admin/class-ig-es-campaign-rules.php:363
427
  msgid "no title"
428
  msgstr ""
429
 
430
+ #: lite/admin/class-ig-es-campaign-rules.php:358
431
+ #: lite/admin/class-ig-es-campaign-rules.php:750
432
  msgid "Any list"
433
  msgstr ""
434
 
435
+ #: lite/admin/class-ig-es-campaign-rules.php:367
436
  msgid "No campaigns available"
437
  msgstr ""
438
 
439
+ #: lite/admin/class-ig-es-campaign-rules.php:432
440
  msgid " or"
441
  msgstr ""
442
 
443
+ #: lite/admin/class-ig-es-campaign-rules.php:442
444
  msgid ") "
445
  msgstr ""
446
 
447
+ #: lite/admin/class-ig-es-campaign-rules.php:512
448
  msgctxt "opening curly double quote"
449
  msgid "&#8220;"
450
  msgstr ""
451
 
452
+ #: lite/admin/class-ig-es-campaign-rules.php:513
453
  msgctxt "closing curly double quote"
454
  msgid "&#8221;"
455
  msgstr ""
456
 
457
+ #: lite/admin/class-ig-es-campaign-rules.php:584
458
  msgid "is in List"
459
  msgstr ""
460
 
461
+ #: lite/admin/class-ig-es-campaign-rules.php:601
462
  #: lite/includes/classes/class-es-admin-settings.php:211
463
  #: lite/includes/classes/class-es-campaign-report.php:189
464
+ #: lite/includes/classes/class-es-contacts-table.php:783
465
+ #: lite/includes/classes/class-es-contacts-table.php:1064
466
  #: lite/includes/classes/class-es-export-subscribers.php:339
467
  #: lite/includes/classes/class-es-forms-table.php:393
468
  #: lite/includes/classes/class-es-import-subscribers.php:563
469
  #: lite/includes/classes/class-es-import-subscribers.php:657
470
+ #: lite/includes/classes/class-es-import-subscribers.php:1052
471
+ #: lite/includes/classes/class-es-import-subscribers.php:1175
472
+ #: lite/includes/compatibilities/elementor/actions/class-es-ig-form-action.php:141
473
+ #: lite/includes/pro-features.php:974
474
+ #: lite/includes/pro-features.php:1505
475
  #: lite/includes/workflows/actions/abstracts/class-ig-es-action-send-email-abstract.php:29
476
  #: lite/public/partials/class-es-shortcode.php:169
477
  #: pro/classes/class-es-pro-campaign-rules.php:35
481
  msgid "Email"
482
  msgstr ""
483
 
484
+ #: lite/admin/class-ig-es-campaign-rules.php:602
485
+ #: lite/includes/pro-features.php:1255
486
+ #: lite/includes/pro-features.php:1504
487
  #: pro/classes/class-es-pro-campaign-rules.php:38
488
  #: pro/classes/class-es-pro-reports-data.php:318
489
  msgid "Country"
490
  msgstr ""
491
 
492
+ #: lite/admin/class-ig-es-campaign-rules.php:615
493
  #: pro/classes/class-es-pro-campaign-rules.php:43
494
  msgid "has received"
495
  msgstr ""
496
 
497
+ #: lite/admin/class-ig-es-campaign-rules.php:616
498
  #: pro/classes/class-es-pro-campaign-rules.php:46
499
  msgid "has not received"
500
  msgstr ""
501
 
502
+ #: lite/admin/class-ig-es-campaign-rules.php:617
503
  #: pro/classes/class-es-pro-campaign-rules.php:49
504
  msgid "has received and opened"
505
  msgstr ""
506
 
507
+ #: lite/admin/class-ig-es-campaign-rules.php:618
508
  #: pro/classes/class-es-pro-campaign-rules.php:52
509
  msgid "has received but not opened"
510
  msgstr ""
511
 
512
+ #: lite/admin/class-ig-es-campaign-rules.php:619
513
  #: pro/classes/class-es-pro-campaign-rules.php:55
514
  msgid "has received and clicked"
515
  msgstr ""
516
 
517
+ #: lite/admin/class-ig-es-campaign-rules.php:620
518
  #: pro/classes/class-es-pro-campaign-rules.php:58
519
  msgid "has received and not clicked"
520
  msgstr ""
521
 
522
+ #: lite/admin/class-ig-es-campaign-rules.php:632
523
  msgid "Any of the Last 5 Campaigns"
524
  msgstr ""
525
 
526
+ #: lite/admin/class-ig-es-campaign-rules.php:633
527
  msgid "Any Campaigns within the last 7 days"
528
  msgstr ""
529
 
530
+ #: lite/admin/class-ig-es-campaign-rules.php:634
531
  msgid "Any Campaigns within the last 1 month"
532
  msgstr ""
533
 
534
+ #: lite/admin/class-ig-es-campaign-rules.php:635
535
  msgid "Any Campaigns within the last 3 months"
536
  msgstr ""
537
 
538
+ #: lite/admin/class-ig-es-campaign-rules.php:636
539
  msgid "Any Campaigns within the last 6 months"
540
  msgstr ""
541
 
542
+ #: lite/admin/class-ig-es-campaign-rules.php:637
543
  msgid "Any Campaigns within the last 12 months"
544
  msgstr ""
545
 
546
+ #: lite/admin/class-ig-es-campaign-rules.php:649
547
+ #: lite/admin/class-ig-es-campaign-rules.php:672
548
+ #: lite/admin/class-ig-es-campaign-rules.php:689
549
+ #: lite/admin/class-ig-es-campaign-rules.php:708
550
  msgid "is"
551
  msgstr ""
552
 
553
+ #: lite/admin/class-ig-es-campaign-rules.php:650
554
+ #: lite/admin/class-ig-es-campaign-rules.php:673
555
+ #: lite/admin/class-ig-es-campaign-rules.php:690
556
+ #: lite/admin/class-ig-es-campaign-rules.php:709
557
  msgid "is not"
558
  msgstr ""
559
 
560
+ #: lite/admin/class-ig-es-campaign-rules.php:651
561
+ #: lite/admin/class-ig-es-campaign-rules.php:691
562
  msgid "contains"
563
  msgstr ""
564
 
565
+ #: lite/admin/class-ig-es-campaign-rules.php:652
566
+ #: lite/admin/class-ig-es-campaign-rules.php:692
567
  msgid "contains not"
568
  msgstr ""
569
 
570
+ #: lite/admin/class-ig-es-campaign-rules.php:653
571
+ #: lite/admin/class-ig-es-campaign-rules.php:693
572
  msgid "begins with"
573
  msgstr ""
574
 
575
+ #: lite/admin/class-ig-es-campaign-rules.php:654
576
+ #: lite/admin/class-ig-es-campaign-rules.php:694
577
  msgid "ends with"
578
  msgstr ""
579
 
580
+ #: lite/admin/class-ig-es-campaign-rules.php:655
581
+ #: lite/admin/class-ig-es-campaign-rules.php:674
582
  msgid "is greater than"
583
  msgstr ""
584
 
585
+ #: lite/admin/class-ig-es-campaign-rules.php:656
586
+ #: lite/admin/class-ig-es-campaign-rules.php:675
587
  msgid "is smaller than"
588
  msgstr ""
589
 
590
+ #: lite/admin/class-ig-es-campaign-rules.php:657
591
+ #: lite/admin/class-ig-es-campaign-rules.php:676
592
  msgid "is greater or equal"
593
  msgstr ""
594
 
595
+ #: lite/admin/class-ig-es-campaign-rules.php:658
596
+ #: lite/admin/class-ig-es-campaign-rules.php:677
597
  msgid "is smaller or equal"
598
  msgstr ""
599
 
600
+ #: lite/admin/class-ig-es-campaign-rules.php:659
601
+ #: lite/admin/class-ig-es-campaign-rules.php:695
602
  msgid "match regex pattern"
603
  msgstr ""
604
 
605
+ #: lite/admin/class-ig-es-campaign-rules.php:660
606
+ #: lite/admin/class-ig-es-campaign-rules.php:696
607
  msgid "does not match regex pattern"
608
  msgstr ""
609
 
610
+ #: lite/admin/class-ig-es-onboarding.php:162
611
  msgid "An error occured. Please try again later."
612
  msgstr ""
613
 
614
  #. translators: 1. Main list name. 2. Default list name.
615
+ #: lite/admin/class-ig-es-onboarding.php:462
616
  msgid "Unable to create %1$s and %2$s list."
617
  msgstr ""
618
 
619
+ #: lite/admin/class-ig-es-onboarding.php:602
620
  #: lite/includes/workflows/db/class-es-db-workflows.php:370
621
  #: lite/includes/workflows/triggers/class-es-trigger-user-registered.php:30
622
  msgid "User Registered"
623
  msgstr ""
624
 
625
+ #: lite/admin/class-ig-es-onboarding.php:717
626
  msgid "Please accept terms & condition"
627
  msgstr ""
628
 
629
  #. translators: Active sidebar name.
630
+ #: lite/admin/class-ig-es-onboarding.php:775
631
  msgid "Adding the form to \"%s\" sidebar, so you can show it on the site"
632
  msgstr ""
633
 
634
  #. translators: Active sidebar name.
635
+ #: lite/admin/class-ig-es-onboarding.php:778
636
  msgid "Unable to add form widget to \"%s\" sidebar. Widget may already exists."
637
  msgstr ""
638
 
639
  #. translators: Active sidebar name.
640
+ #: lite/admin/class-ig-es-onboarding.php:783
641
  msgid "Unable to add form widget to \"%s\" sidebar. No subscription form found."
642
  msgstr ""
643
 
644
+ #: lite/admin/class-ig-es-onboarding.php:835
645
+ #: lite/admin/class-ig-es-onboarding.php:836
646
  msgid "Welcome To Email Subscribers"
647
  msgstr ""
648
 
649
+ #: lite/admin/class-ig-es-onboarding.php:1007
650
  msgid "Seems like your server is not setup correctly to send emails. Please confirm if you're getting any other emails from within WordPress"
651
  msgstr ""
652
 
653
+ #: lite/admin/class-ig-es-onboarding.php:1133
654
  msgid "New Post Published - {{POSTTITLE}}"
655
  msgstr ""
656
 
668
  msgstr ""
669
 
670
  #: lite/admin/partials/dashboard.php:57
671
+ #: lite/includes/classes/class-es-contacts-table.php:133
672
  #: lite/includes/classes/class-es-import-subscribers.php:391
673
  msgid "Import Contacts"
674
  msgstr ""
757
  msgstr ""
758
 
759
  #: lite/admin/partials/dashboard.php:169
760
+ #: lite/includes/classes/class-es-contacts-table.php:320
761
  msgid "Last 60 days"
762
  msgstr ""
763
 
766
  msgstr ""
767
 
768
  #: lite/admin/partials/dashboard.php:201
769
+ #: lite/includes/pro-features.php:1194
770
  msgid "Avg Click Rate"
771
  msgstr ""
772
 
809
  msgid "Create self-expiring, automatic login links for WordPress. Give them to developers when they ask for admin access to your site."
810
  msgstr ""
811
 
812
+ #: lite/admin/partials/help.php:110
813
  #: lite/includes/classes/class-es-info.php:19
814
  msgid "Help & Info"
815
  msgstr ""
816
 
817
+ #: lite/admin/partials/help.php:131
818
  msgid "Database Migration"
819
  msgstr ""
820
 
821
  #. translators: 1. Starting strong tag 2. Closing strong tag
822
+ #: lite/admin/partials/help.php:136
823
  msgid "If you found duplicate campaigns, lists, forms, reports after upgrading from Email Subscribers 3.5.x to 4.x and want to run the database migration again to fix this, please click the below %1$sRun the updater%2$s button."
824
  msgstr ""
825
 
826
  #. translators: 1. Starting strong tag 2. Closing strong tag
827
+ #: lite/admin/partials/help.php:143
828
  msgid "Once you click on %1$sRun the updater%2$s button, it will run the migration process from 3.5.x once again. So, if you have created new campaigns, forms or lists after migration to 4.x earlier, you will lose those data. So, make sure you have a backup with you."
829
  msgstr ""
830
 
831
+ #: lite/admin/partials/help.php:152
832
  #: lite/includes/notices/views/html-notice-update.php:23
833
  msgid "Run the updater"
834
  msgstr ""
835
 
836
+ #: lite/admin/partials/help.php:160
837
  msgid "Get Help?"
838
  msgstr ""
839
 
840
+ #: lite/admin/partials/help.php:170
841
  msgid "Contact US"
842
  msgstr ""
843
 
844
+ #: lite/admin/partials/help.php:210
845
  msgid "Other awesome plugins from same author"
846
  msgstr ""
847
 
848
+ #: lite/admin/partials/help.php:237
849
  #: lite/includes/classes/class-es-campaign-report.php:190
850
  #: lite/includes/classes/class-es-campaigns-table.php:630
851
  #: lite/includes/classes/class-es-export-subscribers.php:341
852
  #: lite/includes/classes/class-es-import-subscribers.php:666
853
+ #: lite/includes/classes/class-es-import-subscribers.php:1178
854
+ #: lite/includes/classes/class-es-reports-table.php:281
855
  #: lite/includes/workflows/class-es-workflows-table.php:338
856
  #: pro/classes/class-es-pro-sequence-report.php:301
857
  msgid "Status"
858
  msgstr ""
859
 
860
+ #: lite/admin/partials/help.php:239
861
+ #: lite/includes/class-es-common.php:393
862
+ #: lite/includes/class-es-common.php:1758
863
+ #: lite/includes/class-es-common.php:2190
864
  #: lite/includes/classes/class-es-campaigns-table.php:314
865
  #: lite/includes/workflows/admin/views/meta-box-save.php:28
866
  #: pro/classes/class-es-pro-reports-data.php:193
868
  msgid "Active"
869
  msgstr ""
870
 
871
+ #: lite/admin/partials/help.php:241
872
+ #: lite/includes/class-es-common.php:394
873
+ #: lite/includes/class-es-common.php:2195
874
  #: lite/includes/workflows/admin/views/meta-box-save.php:27
875
  #: pro/classes/class-es-pro-reports-data.php:198
876
  #: pro/classes/class-es-pro-sequence-report.php:239
877
  msgid "Inactive"
878
  msgstr ""
879
 
880
+ #: lite/admin/partials/help.php:243
881
  msgid "Not Installed"
882
  msgstr ""
883
 
884
+ #: lite/admin/partials/help.php:256
885
  msgid "Install"
886
  msgstr ""
887
 
888
+ #: lite/admin/partials/help.php:259
889
  #: lite/includes/workflows/class-es-workflows-table.php:365
890
  msgid "Activate"
891
  msgstr ""
904
  "\t\t results quickly."
905
  msgstr ""
906
 
907
+ #: lite/admin/partials/onboarding.php:57
908
  msgid "Essentials:"
909
  msgstr ""
910
 
911
+ #: lite/admin/partials/onboarding.php:64
912
  msgid "\"From\" name for emails: "
913
  msgstr ""
914
 
915
+ #: lite/admin/partials/onboarding.php:73
916
  msgid "\"From\" email: "
917
  msgstr ""
918
 
919
+ #: lite/admin/partials/onboarding.php:84
920
  msgid "Email delivery testing:"
921
  msgstr ""
922
 
923
+ #: lite/admin/partials/onboarding.php:89
924
  msgid ""
925
  "Add a couple of your own email addresses below. We will add\n"
926
  "\t\t them to your audience lists."
927
  msgstr ""
928
 
929
+ #: lite/admin/partials/onboarding.php:118
930
  msgid "Your preferences:"
931
  msgstr ""
932
 
933
  #. translators: %s. Plugin name.
934
+ #: lite/admin/partials/onboarding.php:153
935
  msgid "Help us to improve %s by opting in to share non-sensitive plugin usage data. No personal data is tracked or stored."
936
  msgstr ""
937
 
938
+ #: lite/admin/partials/onboarding.php:173
939
  msgid ""
940
  "I want to send email notifications when new blog posts are\n"
941
  "\t\t published"
942
  msgstr ""
943
 
944
+ #: lite/admin/partials/onboarding.php:195
945
  msgid ""
946
  "Enable double opt-in (people have to click a confirmation\n"
947
  "\t\t link in email before they're subscribed)"
948
  msgstr ""
949
 
950
+ #: lite/admin/partials/onboarding.php:214
951
  msgid "Add GDPR consent in subscription forms"
952
  msgstr ""
953
 
954
+ #: lite/admin/partials/onboarding.php:227
955
  msgid "Ok, set it up for me →"
956
  msgstr ""
957
 
958
+ #: lite/admin/partials/onboarding.php:257
959
  msgid "STEP 2 of 3"
960
  msgstr ""
961
 
962
+ #: lite/admin/partials/onboarding.php:261
963
  msgid "Hold on, personalizing for you..."
964
  msgstr ""
965
 
966
+ #: lite/admin/partials/onboarding.php:266
967
  msgid ""
968
  "We'll create audience lists, campaigns and a subscription form.\n"
969
  "\t\t And then try to send a test email to make sure everything works."
970
  msgstr ""
971
 
972
  #. translators: 1: Main List 2: Test List
973
+ #: lite/admin/partials/onboarding.php:282
974
  msgid "Creating audience lists - %1$s &amp; %2$s"
975
  msgstr ""
976
 
977
+ #: lite/admin/partials/onboarding.php:296
978
  msgid "Subscribing you and "
979
  msgstr ""
980
 
981
+ #: lite/admin/partials/onboarding.php:298
982
  msgid " to these lists"
983
  msgstr ""
984
 
985
+ #: lite/admin/partials/onboarding.php:310
986
  msgid "Creating a campaign - newsletter broadcast test"
987
  msgstr ""
988
 
989
+ #: lite/admin/partials/onboarding.php:322
990
  msgid "Creating a campaign - new post notification test"
991
  msgstr ""
992
 
993
+ #: lite/admin/partials/onboarding.php:334
994
  msgid "Creating a subscription opt-in form for the Main list"
995
  msgstr ""
996
 
997
+ #: lite/admin/partials/onboarding.php:347
998
  msgid ""
999
  "Adding the form to an active sidebar, so you can show it on\n"
1000
  "\t\t the site"
1001
  msgstr ""
1002
 
1003
+ #: lite/admin/partials/onboarding.php:365
1004
  msgid "Testing email delivery..."
1005
  msgstr ""
1006
 
1007
+ #: lite/admin/partials/onboarding.php:375
1008
  msgid "Queuing up campaign - newsletter broadcast test"
1009
  msgstr ""
1010
 
1011
+ #: lite/admin/partials/onboarding.php:385
1012
  msgid "Dispatching emails from your server"
1013
  msgstr ""
1014
 
1015
+ #: lite/admin/partials/onboarding.php:396
1016
  msgid "Waiting for test email to arrive on destination server"
1017
  msgstr ""
1018
 
1019
+ #: lite/admin/partials/onboarding.php:407
1020
  msgid "Excellent! Email delivery setup is working well!"
1021
  msgstr ""
1022
 
1023
+ #: lite/admin/partials/onboarding.php:420
1024
  msgid "Continue anyway →"
1025
  msgstr ""
1026
 
1027
+ #: lite/admin/partials/onboarding.php:422
1028
  msgid "All good, let's finish up →"
1029
  msgstr ""
1030
 
1031
+ #: lite/admin/partials/onboarding.php:457
1032
  msgid "STEP 3 of 3"
1033
  msgstr ""
1034
 
1035
+ #: lite/admin/partials/onboarding.php:461
1036
  msgid "Done! Now speed up your success!"
1037
  msgstr ""
1038
 
1039
+ #: lite/admin/partials/onboarding.php:468
1040
  msgid "Setup is complete. Couple of things to support you..."
1041
  msgstr ""
1042
 
1043
+ #: lite/admin/partials/onboarding.php:473
1044
  msgid "Free course: WordPress Email Marketing Masterclass 2021"
1045
  msgstr ""
1046
 
1047
+ #: lite/admin/partials/onboarding.php:477
1048
  msgid ""
1049
  "How to build your list, make sure your email reach your\n"
1050
  "\t\t\t\t audience and influence your audience."
1051
  msgstr ""
1052
 
1053
+ #: lite/admin/partials/onboarding.php:509
1054
  msgid "Premium features for free:"
1055
  msgstr ""
1056
 
1057
+ #: lite/admin/partials/onboarding.php:538
1058
  msgid "Yes, start the trial"
1059
  msgstr ""
1060
 
1061
+ #: lite/admin/partials/onboarding.php:548
1062
  msgid "Recommended next steps:"
1063
  msgstr ""
1064
 
1065
+ #: lite/admin/partials/onboarding.php:551
1066
  msgid "Review \"Settings\" and make adjustments if needed"
1067
  msgstr ""
1068
 
1069
+ #: lite/admin/partials/onboarding.php:552
1070
  msgid "Import your contacts, create new campaigns and test"
1071
  msgstr ""
1072
 
1073
+ #: lite/admin/partials/onboarding.php:555
1074
  #: pro/workflows/triggers/class-es-trigger-wc-product-review-approved.php:25
1075
  msgid "Review"
1076
  msgstr ""
1077
 
1078
+ #: lite/admin/partials/onboarding.php:560
1079
  msgid "documentation"
1080
  msgstr ""
1081
 
1082
+ #: lite/admin/partials/onboarding.php:562
1083
  msgid "if you need any help"
1084
  msgstr ""
1085
 
1086
+ #: lite/admin/partials/onboarding.php:575
1087
  msgid "Complete setup &amp; take me to \"Dashboard\" "
1088
  msgstr ""
1089
 
1090
+ #: lite/admin/partials/onboarding.php:616
1091
  msgid "Email sending did not work"
1092
  msgstr ""
1093
 
1094
+ #: lite/admin/partials/onboarding.php:621
1095
  msgid "Here's the error we encountered:"
1096
  msgstr ""
1097
 
1098
+ #: lite/admin/partials/onboarding.php:632
1099
  msgid ""
1100
  "We recommend you solve this problem quickly after completing\n"
1101
  "\t\t\t\t\t the setup. Do make sure emails are getting delivered before\n"
1102
  "\t\t\t\t\t you send any real campaigns."
1103
  msgstr ""
1104
 
1105
+ #: lite/admin/partials/onboarding.php:651
1106
  msgid " Understood, continue for now →"
1107
  msgstr ""
1108
 
1144
  msgstr ""
1145
 
1146
  #. translators: %s: Cron URL
1147
+ #: lite/includes/class-email-subscribers.php:355
1148
  msgid "WordPress Cron is disabled on your site. Email notifications from Email Subscribers plugin will not be sent automatically. <a href=\"%s\" target=\"_blank\" >Here's how you can enable it.</a>"
1149
  msgstr ""
1150
 
1151
  #. translators: %s: Link to Cpanel URL
1152
+ #: lite/includes/class-email-subscribers.php:357
1153
  msgid "Or schedule Cron in <a href=\"%s\" target=\"_blank\">cPanel</a>"
1154
  msgstr ""
1155
 
1156
  #. translators: %s: ES Pro URL
1157
+ #: lite/includes/class-email-subscribers.php:359
1158
  msgid "Or use <strong><a href=\"%s\" target=\"_blank\">Email Subscribers Pro</a></strong> for automatic Cron support"
1159
  msgstr ""
1160
 
1161
+ #: lite/includes/class-email-subscribers.php:360
1162
  msgid "OK, I Got it!"
1163
  msgstr ""
1164
 
1165
  #. translators: 1: Error message 2: File name 3: Line number
1166
+ #: lite/includes/class-email-subscribers.php:1278
1167
  msgid "%1$s in %2$s on line %3$s"
1168
  msgstr ""
1169
 
1170
+ #: lite/includes/class-email-subscribers.php:1539
1171
  msgid "Icegram WC"
1172
  msgstr ""
1173
 
1174
  #. translators: %1$s - constant that was used
1175
+ #: lite/includes/class-email-subscribers.php:1948
1176
  msgid "Value was set using constant %1$s"
1177
  msgstr ""
1178
 
1179
+ #: lite/includes/class-es-common.php:192
1180
+ #: lite/includes/classes/class-es-contacts-table.php:343
1181
  #: lite/includes/classes/class-es-import-subscribers.php:839
1182
+ #: lite/includes/classes/class-es-import-subscribers.php:1185
1183
  #: lite/includes/classes/class-es-lists-table.php:573
1184
  msgid "Unconfirmed"
1185
  msgstr ""
1186
 
1187
+ #: lite/includes/class-es-common.php:216
1188
  #: lite/includes/classes/class-es-import-subscribers.php:236
1189
  msgid "Select Status"
1190
  msgstr ""
1191
 
1192
+ #: lite/includes/class-es-common.php:350
1193
  msgid "Select Template"
1194
  msgstr ""
1195
 
1196
+ #: lite/includes/class-es-common.php:464
1197
  msgid "Select Categories"
1198
  msgstr ""
1199
 
1200
+ #: lite/includes/class-es-common.php:479
1201
  msgid "All Categories (Also include all categories which will create later)"
1202
  msgstr ""
1203
 
1204
+ #: lite/includes/class-es-common.php:485
1205
  msgid "None (Don't include post from any category)"
1206
  msgstr ""
1207
 
1208
+ #: lite/includes/class-es-common.php:523
1209
  msgid "No Custom Post Types Available"
1210
  msgstr ""
1211
 
1212
+ #: lite/includes/class-es-common.php:539
1213
  msgid "Single Opt-In"
1214
  msgstr ""
1215
 
1216
+ #: lite/includes/class-es-common.php:540
1217
  msgid "Double Opt-In"
1218
  msgstr ""
1219
 
1220
+ #: lite/includes/class-es-common.php:554
1221
  #: pro/pro-class-post-digest.php:149
1222
  msgid "Monday"
1223
  msgstr ""
1224
 
1225
+ #: lite/includes/class-es-common.php:555
1226
  #: pro/pro-class-post-digest.php:150
1227
  msgid "Tuesday"
1228
  msgstr ""
1229
 
1230
+ #: lite/includes/class-es-common.php:556
1231
  #: pro/pro-class-post-digest.php:151
1232
  msgid "Wednesday"
1233
  msgstr ""
1234
 
1235
+ #: lite/includes/class-es-common.php:557
1236
  #: pro/pro-class-post-digest.php:152
1237
  msgid "Thursday"
1238
  msgstr ""
1239
 
1240
+ #: lite/includes/class-es-common.php:558
1241
  #: pro/pro-class-post-digest.php:153
1242
  msgid "Friday"
1243
  msgstr ""
1244
 
1245
+ #: lite/includes/class-es-common.php:559
1246
  #: pro/pro-class-post-digest.php:154
1247
  msgid "Saturday"
1248
  msgstr ""
1249
 
1250
+ #: lite/includes/class-es-common.php:560
1251
  #: pro/pro-class-post-digest.php:148
1252
  msgid "Sunday"
1253
  msgstr ""
1254
 
1255
+ #: lite/includes/class-es-common.php:596
1256
  msgid "Full Size"
1257
  msgstr ""
1258
 
1259
+ #: lite/includes/class-es-common.php:597
1260
  msgid "Medium Size"
1261
  msgstr ""
1262
 
1263
+ #: lite/includes/class-es-common.php:598
1264
  #: lite/includes/classes/class-es-templates-table.php:263
1265
  msgid "Thumbnail"
1266
  msgstr ""
1267
 
1268
+ #: lite/includes/class-es-common.php:1515
1269
  msgid "Top 10 Tips on How to Build an Email List"
1270
  msgstr ""
1271
 
1272
+ #: lite/includes/class-es-common.php:1519
1273
  #: pro/templates/email/es-admin-subscription-summary.php:174
1274
  msgid "Why are Your Email Unsubscribes Increasing and How to Fix Them?"
1275
  msgstr ""
1276
 
1277
+ #: lite/includes/class-es-common.php:1523
1278
  msgid "Balance Email Marketing and Social Media Marketing"
1279
  msgstr ""
1280
 
1281
+ #: lite/includes/class-es-common.php:1527
1282
  msgid "Use social proof to grow blog traffic through email"
1283
  msgstr ""
1284
 
1285
+ #: lite/includes/class-es-common.php:1531
1286
  msgid "5 Simple Tricks to Improve Email Marketing Campaign Results"
1287
  msgstr ""
1288
 
1289
+ #: lite/includes/class-es-common.php:1540
1290
+ #: lite/includes/pro-features.php:150
1291
  msgid "Email Subscribers PRO"
1292
  msgstr ""
1293
 
1294
+ #: lite/includes/class-es-common.php:1542
1295
  msgid "Lifetime"
1296
  msgstr ""
1297
 
1298
+ #: lite/includes/class-es-common.php:1546
1299
  msgid "<b>Email Subscribers Secret Club</b>"
1300
  msgstr ""
1301
 
1302
+ #: lite/includes/class-es-common.php:1548
1303
+ #: lite/includes/feedback.php:123
1304
  msgid "Join Now"
1305
  msgstr ""
1306
 
1307
+ #: lite/includes/class-es-common.php:1726
1308
  msgid "All Types"
1309
  msgstr ""
1310
 
1311
+ #: lite/includes/class-es-common.php:1754
1312
  #: lite/includes/classes/class-es-campaigns-table.php:568
1313
  msgid "Draft"
1314
  msgstr ""
1315
 
1316
+ #: lite/includes/class-es-common.php:1755
1317
+ #: lite/includes/class-es-common.php:2181
1318
  #: lite/includes/classes/class-es-campaign-report.php:237
1319
  #: lite/includes/classes/class-es-campaigns-table.php:549
1320
  #: lite/includes/classes/class-es-campaigns-table.php:587
1321
+ #: lite/includes/classes/class-es-reports-table.php:200
1322
+ #: lite/includes/classes/class-es-reports-table.php:571
1323
  #: pro/classes/class-es-pro-reports-data.php:186
1324
  msgid "Sending"
1325
  msgstr ""
1326
 
1327
+ #: lite/includes/class-es-common.php:1756
1328
  #: lite/includes/classes/class-es-campaigns-table.php:315
1329
  #: lite/includes/classes/class-es-campaigns-table.php:542
1330
  #: lite/includes/classes/class-es-campaigns-table.php:578
1331
+ #: lite/includes/classes/class-es-reports-table.php:216
1332
  #: lite/includes/workflows/admin/views/meta-box-timing.php:36
1333
  msgid "Scheduled"
1334
  msgstr ""
1335
 
1336
+ #: lite/includes/class-es-common.php:1757
1337
+ #: lite/includes/class-es-common.php:2161
1338
  #: lite/includes/classes/class-es-campaign-report.php:221
1339
  #: lite/includes/classes/class-es-campaigns-table.php:556
1340
  #: lite/includes/classes/class-es-campaigns-table.php:605
1341
  #: lite/includes/classes/class-es-reports-table.php:191
1342
+ #: lite/includes/pro-features.php:1139
1343
+ #: lite/includes/pro-features.php:1186
1344
  #: pro/classes/class-es-pro-reports-data.php:170
1345
  #: pro/classes/class-es-pro-reports-data.php:270
1346
  msgid "Sent"
1347
  msgstr ""
1348
 
1349
+ #: lite/includes/class-es-common.php:1782
1350
  #: lite/includes/classes/class-es-campaigns-table.php:690
1351
+ #: lite/includes/classes/class-es-contacts-table.php:1133
1352
  msgid "All Statuses"
1353
  msgstr ""
1354
 
1355
+ #: lite/includes/class-es-common.php:1994
1356
  msgid "Upgrade"
1357
  msgstr ""
1358
 
1359
+ #: lite/includes/class-es-common.php:2030
1360
+ #: lite/includes/classes/class-es-reports-table.php:573
1361
  #: pro/classes/class-es-pro-reports-data.php:878
1362
  msgid "All Status"
1363
  msgstr ""
1364
 
1365
+ #: lite/includes/class-es-common.php:2171
1366
  #: lite/includes/classes/class-es-campaign-report.php:229
1367
+ #: lite/includes/classes/class-es-reports-table.php:570
1368
  #: pro/classes/class-es-pro-reports-data.php:178
1369
  #: pro/partials/es-dashboard.php:60
1370
  msgid "In Queue"
1371
  msgstr ""
1372
 
1373
+ #: lite/includes/class-es-install.php:948
1374
+ #: lite/includes/upgrade/es-update-functions.php:752
1375
  msgid "Your subscription was successful! Kindly check your mailbox and confirm your subscription. If you don't see the email within a few minutes, check the spam/junk folder."
1376
  msgstr ""
1377
 
1402
  #: lite/includes/classes/class-es-admin-settings.php:202
1403
  #: lite/includes/classes/class-es-admin-settings.php:205
1404
  #: lite/includes/classes/class-es-campaigns-table.php:625
1405
+ #: lite/includes/classes/class-es-contacts-table.php:1063
1406
  #: lite/includes/classes/class-es-forms-table.php:410
1407
+ #: lite/includes/classes/class-es-forms-table.php:909
1408
  #: lite/includes/classes/class-es-lists-table.php:569
1409
+ #: lite/includes/compatibilities/elementor/actions/class-es-ig-form-action.php:136
1410
  #: lite/public/partials/class-es-shortcode.php:170
1411
  msgid "Name"
1412
  msgstr ""
1575
  #: lite/includes/classes/class-es-admin-settings.php:453
1576
  #: lite/includes/classes/class-es-admin-settings.php:491
1577
  #: lite/includes/classes/class-es-newsletters.php:355
1578
+ #: lite/includes/classes/class-es-reports-table.php:279
1579
  #: pro/classes/class-es-pro-sequence-report.php:299
1580
  msgid "Subject"
1581
  msgstr ""
1642
  msgstr ""
1643
 
1644
  #: lite/includes/classes/class-es-admin-settings.php:489
1645
+ #: lite/includes/classes/class-es-mailer.php:362
1646
  msgid "Campaign Sent!"
1647
  msgstr ""
1648
 
1729
  msgid "Seeing spam signups from particular domains? Enter domains names (one per line) that you want to block here."
1730
  msgstr ""
1731
 
1732
+ #: lite/includes/classes/class-es-admin-settings.php:846
1733
  msgid "Save Settings"
1734
  msgstr ""
1735
 
1779
  #: lite/includes/classes/class-es-campaigns-table.php:448
1780
  #: lite/includes/classes/class-es-campaigns-table.php:479
1781
  #: lite/includes/classes/class-es-reports-table.php:16
1782
+ #: lite/includes/pro-features.php:1131
1783
  #: pro/classes/class-es-pro-reports-data.php:154
1784
  #: pro/classes/class-es-pro-sequence-report.php:20
1785
  msgid "Report"
1805
  msgstr ""
1806
 
1807
  #: lite/includes/classes/class-es-campaign-report.php:245
1808
+ #: lite/includes/classes/class-es-contacts-table.php:351
1809
+ #: lite/includes/pro-features.php:1170
1810
  #: pro/classes/class-es-pro-reports-data.php:247
1811
  #: pro/classes/class-es-pro-reports-data.php:875
1812
  msgid "Opened"
1813
  msgstr ""
1814
 
1815
+ #: lite/includes/classes/class-es-campaign-report.php:457
1816
  msgid "Campaign Analytics"
1817
  msgstr ""
1818
 
1865
 
1866
  #: lite/includes/classes/class-es-campaigns-table.php:317
1867
  #: lite/includes/classes/class-es-campaigns-table.php:596
1868
+ #: lite/includes/classes/class-es-reports-table.php:208
1869
  msgid "Paused"
1870
  msgstr ""
1871
 
1884
 
1885
  #: lite/includes/classes/class-es-campaigns-table.php:438
1886
  #: lite/includes/classes/class-es-campaigns-table.php:465
1887
+ #: lite/includes/classes/class-es-contacts-table.php:1025
1888
+ #: lite/includes/classes/class-es-forms-table.php:892
1889
  #: lite/includes/classes/class-es-lists-table.php:547
1890
  #: lite/includes/workflows/admin/views/action.php:28
1891
  #: lite/includes/workflows/class-es-workflows-table.php:305
1892
  msgid "Edit"
1893
  msgstr ""
1894
 
1895
+ #: lite/includes/classes/class-es-campaigns-table.php:488
1896
+ #: lite/includes/classes/class-es-contacts-table.php:1027
1897
+ #: lite/includes/classes/class-es-contacts-table.php:1099
1898
+ #: lite/includes/classes/class-es-forms-table.php:894
1899
+ #: lite/includes/classes/class-es-forms-table.php:940