Email Subscribers & Newsletters - Version 4.5.3

Version Description

Download this release

Release Info

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

Code changes from version 4.5.2 to 4.5.3

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.5.2
7
  * Author: Icegram
8
  * Author URI: https://www.icegram.com/
9
  * Requires at least: 3.9
@@ -156,7 +156,7 @@ if ( $is_premium ) {
156
  /* ***************************** Initial Compatibility Work (End) ******************* */
157
 
158
  if ( ! defined( 'ES_PLUGIN_VERSION' ) ) {
159
- define( 'ES_PLUGIN_VERSION', '4.5.2' );
160
  }
161
 
162
  // Plugin Folder Path.
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.5.3
7
  * Author: Icegram
8
  * Author URI: https://www.icegram.com/
9
  * Requires at least: 3.9
156
  /* ***************************** Initial Compatibility Work (End) ******************* */
157
 
158
  if ( ! defined( 'ES_PLUGIN_VERSION' ) ) {
159
+ define( 'ES_PLUGIN_VERSION', '4.5.3' );
160
  }
161
 
162
  // Plugin Folder Path.
lite/admin/class-email-subscribers-admin.php CHANGED
@@ -156,6 +156,15 @@ class Email_Subscribers_Admin {
156
 
157
  wp_localize_script( $this->email_subscribers . '-workflows', 'ig_es_workflows_data', $workflows_data );
158
 
 
 
 
 
 
 
 
 
 
159
  }
160
 
161
  //timepicker
156
 
157
  wp_localize_script( $this->email_subscribers . '-workflows', 'ig_es_workflows_data', $workflows_data );
158
 
159
+ if( ! function_exists( 'ig_es_wp_js_editor_admin_scripts' ) ) {
160
+ /**
161
+ * Include WP JS Editor library's main file. This file contains required functions to enqueue required js file which being used to create WordPress editor dynamcially.
162
+ */
163
+ require_once ES_PLUGIN_DIR . 'lite/includes/libraries/wp-js-editor/wp-js-editor.php';
164
+ }
165
+
166
+ // Load required html/js for dynamic WordPress editor.
167
+ ig_es_wp_js_editor_admin_scripts();
168
  }
169
 
170
  //timepicker
lite/admin/js/email-subscribers-admin.js CHANGED
@@ -598,4 +598,29 @@ function ig_es_show_broadcast_preview_in_popup() {
598
  }).done(function(){
599
  jQuery(template_button).next('.es-loader').hide();
600
  });
601
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
598
  }).done(function(){
599
  jQuery(template_button).next('.es-loader').hide();
600
  });
601
+ }
602
+
603
+ jQuery.fn.extend({
604
+ ig_es_select2: function() {
605
+ return this.each(function() {
606
+ let multiselect_elem = jQuery(this);
607
+
608
+ let first_option_elem = jQuery(multiselect_elem).find('option:first');
609
+ let first_option_vallue = jQuery(first_option_elem).attr('value');
610
+ let placeholder_label = '';
611
+
612
+ if( '' === first_option_vallue || '0' === first_option_vallue ) {
613
+
614
+ // Get placeholder label from the first option.
615
+ placeholder_label = jQuery(first_option_elem).text();
616
+
617
+ // Remove it from option to avoid being shown and allowing users to select it as an option in Select2's options panel.
618
+ jQuery(first_option_elem).remove();
619
+ }
620
+
621
+ jQuery(multiselect_elem).select2({
622
+ placeholder: placeholder_label, // Add placeholder label using first option's text.
623
+ });
624
+ });
625
+ }
626
+ });
lite/includes/class-email-subscribers.php CHANGED
@@ -709,6 +709,7 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
709
  'lite/includes/workflows/fields/class-es-time.php',
710
  'lite/includes/workflows/fields/class-es-select.php',
711
  'lite/includes/workflows/fields/class-es-checkbox.php',
 
712
 
713
  // Workflow Admin
714
  'lite/includes/workflows/admin/class-es-workflow-admin.php',
@@ -722,6 +723,9 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
722
  'lite/includes/workflows/triggers/class-es-trigger-user-updated.php',
723
  'lite/includes/workflows/class-es-workflow-triggers.php',
724
 
 
 
 
725
  // Workflow Actions.
726
  'lite/includes/workflows/actions/class-es-action-add-to-list.php',
727
  'lite/includes/workflows/actions/class-es-action-move-contact.php',
@@ -761,9 +765,23 @@ if ( ! class_exists( 'Email_Subscribers' ) ) {
761
  'starter/workflows/triggers/class-es-trigger-gravity-forms-submitted.php',
762
  'starter/workflows/triggers/class-es-trigger-forminator-forms-submitted.php',
763
 
 
 
 
 
 
 
 
 
 
 
 
 
 
764
  // Actions from Pro version
765
  'pro/workflows/actions/class-es-action-move-to-list.php',
766
  'pro/workflows/actions/class-es-action-remove-from-list.php',
 
767
 
768
  // Workflow Loader
769
  'lite/includes/workflows/class-es-workflow-loader.php',
709
  'lite/includes/workflows/fields/class-es-time.php',
710
  'lite/includes/workflows/fields/class-es-select.php',
711
  'lite/includes/workflows/fields/class-es-checkbox.php',
712
+ 'lite/includes/workflows/fields/class-es-wp-editor.php',
713
 
714
  // Workflow Admin
715
  'lite/includes/workflows/admin/class-es-workflow-admin.php',
723
  'lite/includes/workflows/triggers/class-es-trigger-user-updated.php',
724
  'lite/includes/workflows/class-es-workflow-triggers.php',
725
 
726
+ // Abstracts workflow actions
727
+ 'lite/includes/workflows/actions/abstracts/class-ig-es-action-send-email-abstract.php',
728
+
729
  // Workflow Actions.
730
  'lite/includes/workflows/actions/class-es-action-add-to-list.php',
731
  'lite/includes/workflows/actions/class-es-action-move-contact.php',
765
  'starter/workflows/triggers/class-es-trigger-gravity-forms-submitted.php',
766
  'starter/workflows/triggers/class-es-trigger-forminator-forms-submitted.php',
767
 
768
+ // Triggers from Pro version
769
+ 'pro/workflows/triggers/class-es-trigger-wc-order-refunded.php',
770
+ 'pro/workflows/triggers/class-es-trigger-wc-product-review-approved.php',
771
+
772
+ // Trigger Extra fields from Pro version
773
+ 'pro/workflows/triggers/extras/class-es-pro-trigger-user-registered.php',
774
+
775
+ // Action Extra fields from Pro version
776
+ 'pro/workflows/actions/extras/class-es-pro-action-add-to-list.php',
777
+
778
+ // Data Types from Pro version
779
+ 'pro/workflows/data-types/class-es-data-type-review.php',
780
+
781
  // Actions from Pro version
782
  'pro/workflows/actions/class-es-action-move-to-list.php',
783
  'pro/workflows/actions/class-es-action-remove-from-list.php',
784
+ 'pro/workflows/actions/class-es-action-send-email.php',
785
 
786
  // Workflow Loader
787
  'lite/includes/workflows/class-es-workflow-loader.php',
lite/includes/class-es-install.php CHANGED
@@ -255,7 +255,8 @@ if ( ! class_exists( 'ES_Install' ) ) {
255
 
256
  self::install();
257
  }
258
-
 
259
  }
260
 
261
  /**
255
 
256
  self::install();
257
  }
258
+ // Do we need to load templates?
259
+ self::load_templates();
260
  }
261
 
262
  /**
lite/includes/classes/class-es-mailer.php CHANGED
@@ -570,8 +570,10 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
570
  if( 'newsletter' === $campaign_type ) {
571
  $from_name = ! empty( $campaign['from_name'] ) ? $campaign['from_name'] : '';
572
  $from_email = ! empty( $campaign['from_email'] ) ? $campaign['from_email'] : '';
 
573
  $sender_data['from_name'] = $from_name;
574
  $sender_data['from_email'] = $from_email;
 
575
  }
576
  }
577
  }
@@ -680,6 +682,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
680
  if( ! empty( $sender_data ) ) {
681
  $sender_name = ! empty( $sender_data['from_name'] ) ? $sender_data['from_name'] : '';
682
  $sender_email = ! empty( $sender_data['from_email'] ) ? $sender_data['from_email'] : '';
 
683
  }
684
 
685
  // If sender name is not passed then fetch it from ES settings.
@@ -692,6 +695,9 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
692
  $sender_email = $this->get_from_email();
693
  }
694
 
 
 
 
695
 
696
  $subject = html_entity_decode( $subject, ENT_QUOTES, get_bloginfo( 'charset' ) );
697
 
@@ -704,7 +710,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
704
  $headers = array(
705
  "From: \"$sender_name\" <$sender_email>",
706
  "Return-Path: <" . $sender_email . ">",
707
- "Reply-To: \"" . $sender_name . "\" <" . $sender_email . ">",
708
  "Content-Type: text/html; charset=\"" . get_bloginfo( 'charset' ) . "\""
709
  );
710
 
570
  if( 'newsletter' === $campaign_type ) {
571
  $from_name = ! empty( $campaign['from_name'] ) ? $campaign['from_name'] : '';
572
  $from_email = ! empty( $campaign['from_email'] ) ? $campaign['from_email'] : '';
573
+ $reply_to_email = ! empty( $campaign['reply_to_email'] ) ? $campaign['reply_to_email'] : '';
574
  $sender_data['from_name'] = $from_name;
575
  $sender_data['from_email'] = $from_email;
576
+ $sender_data['reply_to_email'] = $reply_to_email;
577
  }
578
  }
579
  }
682
  if( ! empty( $sender_data ) ) {
683
  $sender_name = ! empty( $sender_data['from_name'] ) ? $sender_data['from_name'] : '';
684
  $sender_email = ! empty( $sender_data['from_email'] ) ? $sender_data['from_email'] : '';
685
+ $reply_to_email = ! empty( $sender_data['reply_to_email'] ) ? $sender_data['reply_to_email'] : '';
686
  }
687
 
688
  // If sender name is not passed then fetch it from ES settings.
695
  $sender_email = $this->get_from_email();
696
  }
697
 
698
+ if( empty( $reply_to_email ) ) {
699
+ $reply_to_email = $this->get_from_email();
700
+ }
701
 
702
  $subject = html_entity_decode( $subject, ENT_QUOTES, get_bloginfo( 'charset' ) );
703
 
710
  $headers = array(
711
  "From: \"$sender_name\" <$sender_email>",
712
  "Return-Path: <" . $sender_email . ">",
713
+ "Reply-To: <" . $reply_to_email . ">",
714
  "Content-Type: text/html; charset=\"" . get_bloginfo( 'charset' ) . "\""
715
  );
716
 
lite/includes/classes/class-es-newsletters.php CHANGED
@@ -140,20 +140,21 @@ class ES_Newsletters {
140
 
141
  if ( ! empty( $broadcast_id ) ) {
142
 
143
- $broadcast_query = $wpdb->prepare( "SELECT * FROM " . IG_CAMPAIGNS_TABLE . " WHERE id = %d LIMIT 0, 1", $broadcast_id );
144
- $broadcasts = $wpdb->get_results( $broadcast_query, ARRAY_A );
145
- $broadcast = array_shift( $broadcasts );
146
- $broadcast_data = array(
147
- 'id' => $broadcast['id'],
148
- 'name' => $broadcast['name'],
149
- 'subject' => $broadcast['subject'],
150
- 'from_name' => $broadcast['from_name'],
151
- 'from_email' => $broadcast['from_email'],
152
- 'body' => $broadcast['body'],
153
- 'list_ids' => $broadcast['list_ids'],
154
- 'template_id' => $broadcast['base_template_id'],
155
- 'status' => $broadcast['status'],
156
- 'meta' => maybe_unserialize( $broadcast['meta'] ),
 
157
  );
158
  }
159
 
@@ -179,6 +180,7 @@ class ES_Newsletters {
179
  $broadcast_id = ! empty( $broadcast_data['id'] ) ? $broadcast_data['id'] : '';
180
  $broadcast_from_name = ! empty( $broadcast_data['from_name'] ) ? $broadcast_data['from_name'] : get_option( 'ig_es_from_name' );
181
  $broadcast_email = ! empty( $broadcast_data['from_email'] ) ? $broadcast_data['from_email'] : $from_email;
 
182
  $broadcast_subject = ! empty( $broadcast_data['subject'] ) ? $broadcast_data['subject'] : '';
183
  $broadcast_pre_header = ! empty( $broadcast_data['pre_header'] ) ? $broadcast_data['pre_header'] : '';
184
  $broadcast_status = ! empty( $broadcast_data['status'] ) ? (int) $broadcast_data['status'] : 0;
@@ -334,6 +336,10 @@ class ES_Newsletters {
334
  <label for="from_email" class="text-sm font-medium leading-5 text-gray-700"><?php echo esc_html__( 'From Email', 'email-subscribers' ); ?></label>
335
  <input id="from_email" class="block w-full mt-1 text-sm leading-5 border-gray-400 rounded-md shadow-sm form-input" name="broadcast_data[from_email]" value="<?php echo esc_attr( $broadcast_email ); ?>"/>
336
  </div>
 
 
 
 
337
 
338
  <div class="w-full px-4 pt-1 pb-2 mt-1">
339
  <label for="message" class="text-sm font-medium leading-5 text-gray-700"><?php echo esc_html__( 'Message', 'email-subscribers' ); ?></label>
140
 
141
  if ( ! empty( $broadcast_id ) ) {
142
 
143
+ $broadcast_query = $wpdb->prepare( "SELECT * FROM " . IG_CAMPAIGNS_TABLE . " WHERE id = %d LIMIT 0, 1", $broadcast_id );
144
+ $broadcasts = $wpdb->get_results( $broadcast_query, ARRAY_A );
145
+ $broadcast = array_shift( $broadcasts );
146
+ $broadcast_data = array(
147
+ 'id' => $broadcast['id'],
148
+ 'name' => $broadcast['name'],
149
+ 'subject' => $broadcast['subject'],
150
+ 'from_name' => $broadcast['from_name'],
151
+ 'from_email' => $broadcast['from_email'],
152
+ 'reply_to_email' => $broadcast['reply_to_email'],
153
+ 'body' => $broadcast['body'],
154
+ 'list_ids' => $broadcast['list_ids'],
155
+ 'template_id' => $broadcast['base_template_id'],
156
+ 'status' => $broadcast['status'],
157
+ 'meta' => maybe_unserialize( $broadcast['meta'] ),
158
  );
159
  }
160
 
180
  $broadcast_id = ! empty( $broadcast_data['id'] ) ? $broadcast_data['id'] : '';
181
  $broadcast_from_name = ! empty( $broadcast_data['from_name'] ) ? $broadcast_data['from_name'] : get_option( 'ig_es_from_name' );
182
  $broadcast_email = ! empty( $broadcast_data['from_email'] ) ? $broadcast_data['from_email'] : $from_email;
183
+ $broadcast_reply_to = ! empty( $broadcast_data['reply_to_email'] ) ? $broadcast_data['reply_to_email'] : $from_email;
184
  $broadcast_subject = ! empty( $broadcast_data['subject'] ) ? $broadcast_data['subject'] : '';
185
  $broadcast_pre_header = ! empty( $broadcast_data['pre_header'] ) ? $broadcast_data['pre_header'] : '';
186
  $broadcast_status = ! empty( $broadcast_data['status'] ) ? (int) $broadcast_data['status'] : 0;
336
  <label for="from_email" class="text-sm font-medium leading-5 text-gray-700"><?php echo esc_html__( 'From Email', 'email-subscribers' ); ?></label>
337
  <input id="from_email" class="block w-full mt-1 text-sm leading-5 border-gray-400 rounded-md shadow-sm form-input" name="broadcast_data[from_email]" value="<?php echo esc_attr( $broadcast_email ); ?>"/>
338
  </div>
339
+ <div class="block px-4 py-2">
340
+ <label for="reply_to" class="text-sm font-medium leading-5 text-gray-700"><?php echo esc_html__( 'Reply To', 'email-subscribers' ); ?></label>
341
+ <input id="reply_to" class="block w-full mt-1 text-sm leading-5 border-gray-400 rounded-md shadow-sm form-input" name="broadcast_data[reply_to_email]" value="<?php echo esc_attr( $broadcast_reply_to ); ?>"/>
342
+ </div>
343
 
344
  <div class="w-full px-4 pt-1 pb-2 mt-1">
345
  <label for="message" class="text-sm font-medium leading-5 text-gray-700"><?php echo esc_html__( 'Message', 'email-subscribers' ); ?></label>
lite/includes/db/class-es-db-campaigns.php CHANGED
@@ -693,7 +693,7 @@ class ES_DB_Campaigns extends ES_DB {
693
 
694
  $id_str = '';
695
  $campaign_ids = esc_sql( $campaign_ids );
696
-
697
  if ( is_array( $campaign_ids ) && count( $campaign_ids ) > 0 ) {
698
  $id_str = implode( ',', $campaign_ids );
699
  } elseif ( is_numeric( $campaign_ids ) ) {
@@ -708,6 +708,14 @@ class ES_DB_Campaigns extends ES_DB {
708
  $sql = $wpdb->prepare( $sql, $status ); // phpcs:ignore
709
 
710
  $updated = $wpdb->query( $sql ); // phpcs:ignore
 
 
 
 
 
 
 
 
711
  }
712
 
713
  return $updated;
693
 
694
  $id_str = '';
695
  $campaign_ids = esc_sql( $campaign_ids );
696
+
697
  if ( is_array( $campaign_ids ) && count( $campaign_ids ) > 0 ) {
698
  $id_str = implode( ',', $campaign_ids );
699
  } elseif ( is_numeric( $campaign_ids ) ) {
708
  $sql = $wpdb->prepare( $sql, $status ); // phpcs:ignore
709
 
710
  $updated = $wpdb->query( $sql ); // phpcs:ignore
711
+
712
+ //Changing status of child campaigns along with its parent campaign id
713
+ $query = 'UPDATE ' . IG_CAMPAIGNS_TABLE . ' SET status = %d';
714
+
715
+ $query .= " WHERE parent_id IN ($id_str)";
716
+
717
+ $wpdb->query( $wpdb->prepare( $query, $status ) );
718
+
719
  }
720
 
721
  return $updated;
lite/includes/libraries/wp-js-editor/wp-js-editor.js ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * JavaScript Wordpress editor
3
+ * Author: Shrimp2t
4
+ * Author URI: http://shrimp2t.com
5
+ * Version: 1.0.0
6
+ * License:
7
+ * Copyright (c) 2013 Ante Primorac
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ * Usage:
26
+ * client side(jQuery):
27
+ * $( 'textarea').wp_js_editor();
28
+ */
29
+
30
+
31
+ (function ( $ ) {
32
+
33
+ window._wpEditor = {
34
+ init: function( id , content, settings ){
35
+ var _id = '__wp_mce_editor__';
36
+ var _tpl = $( '#_wp-mce-editor-tpl').html();
37
+ if ( typeof content === "undefined" ){
38
+ content = '';
39
+ }
40
+
41
+ if ( typeof window.tinyMCEPreInit.mceInit[ _id ] !== "undefined" ) {
42
+
43
+ var tmceInit = _.clone( window.tinyMCEPreInit.mceInit[_id] );
44
+ var qtInit = _.clone( window.tinyMCEPreInit.qtInit[_id] );
45
+
46
+ tmceInit = $.extend( tmceInit , settings.tinymce );
47
+ qtInit = $.extend( qtInit , settings.qtag );
48
+
49
+ var tpl = _tpl.replace( new RegExp(_id,"g"), id );
50
+
51
+ // Email Subscriber custom code start.
52
+ var textarea_name = $('#' + id ).attr('name');
53
+ // Email Subscriber custom code end.
54
+
55
+ var template = $( tpl );
56
+ $( "#"+id ).replaceWith( template );
57
+
58
+ // Email Subscriber custom code start.
59
+ if( 'undefined' !== typeof textarea_name ) {
60
+ $( "#"+id ).attr('name', textarea_name);
61
+ }
62
+ // Email Subscriber custom code end.
63
+
64
+ // set content
65
+ $( '#'+id ).val( content );
66
+
67
+ $wrap = tinymce.$( '#wp-' + id + '-wrap' );
68
+
69
+ tmceInit.body_class = tmceInit.body_class.replace(new RegExp(_id,"g"), id );
70
+ tmceInit.selector = tmceInit.selector.replace(new RegExp(_id,"g"), id );
71
+ tmceInit.cache_suffix = '';
72
+
73
+ $wrap.removeClass( 'html-active').addClass( 'tmce-active' );
74
+
75
+ tmceInit.init_instance_callback = function( editor ){
76
+ //switchEditors.go( new_id, 'tmce' );
77
+ if ( typeof settings === 'object' ) {
78
+ // editor.theme.resizeTo('100%', 500);
79
+ if( typeof settings.init_instance_callback === "function" ) {
80
+ settings.init_instance_callback( editor );
81
+ }
82
+
83
+ if (settings.sync_id !== '') {
84
+ if (typeof settings.sync_id === 'string') {
85
+ editor.on('keyup change', function (e) {
86
+ $('#' + settings.sync_id).val(editor.getContent() ).trigger('change');
87
+ });
88
+ } else {
89
+ editor.on('keyup change', function (e) {
90
+ settings.sync_id.val( editor.getContent() ).trigger('change');
91
+ });
92
+ }
93
+ }
94
+ }
95
+ };
96
+
97
+ tinyMCEPreInit.mceInit[ id ] = tmceInit;
98
+ tmceInit['content'] = 'test content';
99
+
100
+ qtInit.id = id;
101
+ tinyMCEPreInit.qtInit[ id ] = qtInit;
102
+
103
+ if ( $wrap.hasClass( 'tmce-active' ) || ! tinyMCEPreInit.qtInit.hasOwnProperty( id ) ) {
104
+ tinymce.init( tmceInit );
105
+ if ( ! window.wpActiveEditor ) {
106
+ window.wpActiveEditor = id;
107
+ }
108
+ }
109
+
110
+ if ( typeof quicktags !== 'undefined' ) {
111
+ quicktags( qtInit );
112
+ if ( ! window.wpActiveEditor ) {
113
+ window.wpActiveEditor = id;
114
+ }
115
+
116
+ }
117
+
118
+ }
119
+ },
120
+
121
+ sync: function(){
122
+ //
123
+ },
124
+
125
+ remove: function( id ){
126
+ var content = '';
127
+ var editor = false;
128
+ if ( editor = tinymce.get(id) ) {
129
+ content = editor.getContent();
130
+ editor.remove();
131
+ } else {
132
+ content = $( '#'+id ).val();
133
+ }
134
+
135
+ if ( $( '#wp-' + id + '-wrap').length > 0 ) {
136
+ window._wpEditorBackUp = window._wpEditorBackUp || {};
137
+ if ( typeof window._wpEditorBackUp[ id ] !== "undefined" ) {
138
+ $( '#wp-' + id + '-wrap').replaceWith( window._wpEditorBackUp[ id ] );
139
+ }
140
+ }
141
+
142
+ $( '#'+id ).val( content );
143
+ }
144
+
145
+ };
146
+
147
+
148
+ $.fn.wp_js_editor = function( options ) {
149
+
150
+ // This is the easiest way to have default options.
151
+ if ( options !== 'remove' ) {
152
+ options = $.extend({
153
+ sync_id: "", // sync to another text area
154
+ tinymce: {}, // tinymce setting
155
+ qtag: {}, // quick tag settings
156
+ init_instance_callback: function(){} // quick tag settings
157
+ }, options );
158
+ } else{
159
+ options = 'remove';
160
+ }
161
+
162
+ return this.each( function( ) {
163
+ var edit_area = $( this );
164
+ edit_area.uniqueId();
165
+ // Make sure edit area have a id attribute
166
+ var id = edit_area.attr( 'id' ) || '';
167
+ if ( id === '' ){
168
+ return ;
169
+ }
170
+
171
+ if ( 'remove' !== options ) {
172
+ window._wpEditorBackUp = window._wpEditorBackUp || {};
173
+ window._wpEditorBackUp[ id ] = edit_area;
174
+ window._wpEditor.init( id, edit_area.val(), options );
175
+ } else {
176
+ window._wpEditor.remove( id );
177
+ }
178
+
179
+ });
180
+
181
+ };
182
+
183
+ }( jQuery ));
184
+
lite/includes/libraries/wp-js-editor/wp-js-editor.php ADDED
@@ -0,0 +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
+
lite/includes/workflows/abstracts/class-es-workflow-action.php CHANGED
@@ -124,13 +124,10 @@ abstract class ES_Workflow_Action {
124
  * Method to load the action's fields.
125
  *
126
  * @since 4.4.1
 
 
127
  */
128
- public function load_fields() {
129
- $action_data = array(
130
- 'action' => $this,
131
- );
132
- do_action( $this->name . '_load_fields', $action_data );
133
- }
134
 
135
  /**
136
  * Method to set the action's admin props.
@@ -268,12 +265,17 @@ abstract class ES_Workflow_Action {
268
  * @since 4.4.1
269
  *
270
  * @modified 4.4.3 Removed isset condition to allow latest list of fields every time when called.
 
 
271
  */
272
  public function get_fields() {
273
 
274
  $this->fields = array();
275
  $this->load_fields();
276
 
 
 
 
277
  return $this->fields;
278
  }
279
 
124
  * Method to load the action's fields.
125
  *
126
  * @since 4.4.1
127
+ *
128
+ * @modified 4.5.3 Removed dependency to modify child action file to load extra fields.
129
  */
130
+ public function load_fields() {}
 
 
 
 
 
131
 
132
  /**
133
  * Method to set the action's admin props.
265
  * @since 4.4.1
266
  *
267
  * @modified 4.4.3 Removed isset condition to allow latest list of fields every time when called.
268
+ *
269
+ * @modified 4.5.3 Added new action action_name_load_extra_fileds to allow loading of extra fields for action.
270
  */
271
  public function get_fields() {
272
 
273
  $this->fields = array();
274
  $this->load_fields();
275
 
276
+ // Load extra fields for workflow action.
277
+ do_action( $this->name . '_load_extra_fields', $this );
278
+
279
  return $this->fields;
280
  }
281
 
lite/includes/workflows/abstracts/class-es-workflow-trigger.php CHANGED
@@ -158,10 +158,17 @@ abstract class ES_Workflow_Trigger {
158
  * Field loader
159
  *
160
  * @since 4.4.1
 
 
161
  */
162
  public function maybe_load_fields() {
163
  if ( ! $this->has_loaded_fields ) {
 
164
  $this->load_fields();
 
 
 
 
165
  $this->has_loaded_fields = true;
166
  }
167
  }
158
  * Field loader
159
  *
160
  * @since 4.4.1
161
+ *
162
+ * @modified 4.5.3 Added new action trigger_name_load_extra_fields to allow loading of extra fields for given trigger.
163
  */
164
  public function maybe_load_fields() {
165
  if ( ! $this->has_loaded_fields ) {
166
+ // Load fields defined in trigger.
167
  $this->load_fields();
168
+
169
+ // Load extra fields for given trigger.
170
+ do_action( $this->name . '_load_extra_fields', $this );
171
+
172
  $this->has_loaded_fields = true;
173
  }
174
  }
lite/includes/workflows/actions/abstracts/class-ig-es-action-send-email-abstract.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Action to send an email to provided email address.
4
+ *
5
+ * @author Icegram
6
+ * @since 4.5.3
7
+ * @version 1.0
8
+ * @package Email Subscribers
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
+
15
+ /**
16
+ * @class ES_Action_Send_Email_Abstract
17
+ *
18
+ * @since 4.5.3
19
+ */
20
+ abstract class ES_Action_Send_Email_Abstract extends ES_Workflow_Action {
21
+
22
+ /**
23
+ * Load admin props.
24
+ *
25
+ * @since 4.5.3
26
+ */
27
+ public function load_admin_details() {
28
+ $this->group = __( 'Email', 'email-subscribers' );
29
+ }
30
+
31
+ /**
32
+ * Load fields.
33
+ *
34
+ * @since 4.5.3
35
+ */
36
+ public function load_fields() {
37
+ $send_to = new ES_Text();
38
+ $send_to->set_name( 'ig-es-send-to' );
39
+ $send_to->set_title( __( 'Send To', 'email-subscribers' ) );
40
+ $send_to->set_description( __( 'Enter emails here or use variable such as {{EMAIL}}. Multiple emails can be separated by commas.', 'email-subscribers' ) );
41
+ $send_to->set_placeholder( __( 'E.g. {{EMAIL}}, admin@example.com', 'email-subscribers' ) );
42
+ $send_to->set_required();
43
+
44
+ $subject = new ES_Text();
45
+ $subject->set_name( 'ig-es-email-subject' );
46
+ $subject->set_title( __( 'Email subject', 'email-subscribers' ) );
47
+ $subject->set_required();
48
+
49
+ $this->add_field( $send_to );
50
+ $this->add_field( $subject );
51
+ }
52
+ }
lite/includes/workflows/actions/class-es-action-add-to-list.php CHANGED
@@ -46,9 +46,6 @@ class ES_Action_Add_To_List extends ES_Workflow_Action {
46
  $list_field->set_options( $lists );
47
  $list_field->set_required();
48
  $this->add_field( $list_field );
49
-
50
- parent::load_fields();
51
-
52
  }
53
 
54
  /**
@@ -73,49 +70,6 @@ class ES_Action_Add_To_List extends ES_Workflow_Action {
73
  }
74
  $data = $data_type->get_data( $data_item );
75
  $this->add_contact( $list_id, $data );
76
-
77
- // Check if we have WC_Order object.
78
- if( $data_item instanceof WC_Order && is_callable( array( $data_item, 'get_items' ) ) ) {
79
-
80
- // Get product items from the order.
81
- $line_items = $data_item->get_items();
82
-
83
- if( ! empty( $line_items ) ) {
84
- $product_list_enabled = $this->get_option( 'ig-es-product-list-enabled' );
85
- $variation_list_enabled = $this->get_option( 'ig-es-variation-list-enabled' );
86
- $action_add_to_list = new ES_Action_Add_To_List();
87
- foreach ( $line_items as $line_item ) {
88
- $product = $line_item->get_product();
89
-
90
- if( $product instanceof WC_Product ) {
91
-
92
- // If product is a variation then get its parent product.
93
- if( $product->is_type( 'variation' ) ) {
94
- $parent_product_id = $product->get_parent_id();
95
- $parent_product = wc_get_product( $parent_product_id );
96
-
97
- // Check if list also has to be created for variation product also.
98
- if( $variation_list_enabled ) {
99
- $variation_list_id = $this->create_list_from_product( $product );
100
- if( ! empty( $variation_list_id ) ) {
101
- $action_add_to_list->add_contact( $variation_list_id, $data );
102
- }
103
- }
104
- } else {
105
- $parent_product = $product;
106
- }
107
-
108
- if( $product_list_enabled ) {
109
- $parent_list_id = $this->create_list_from_product( $parent_product );
110
- if( ! empty( $parent_list_id ) ) {
111
- $action_add_to_list->add_contact( $parent_list_id, $data );
112
- }
113
- }
114
- }
115
-
116
- }
117
- }
118
- }
119
  }
120
  }
121
 
@@ -182,43 +136,4 @@ class ES_Action_Add_To_List extends ES_Workflow_Action {
182
 
183
  do_action( 'ig_es_add_contact', $contact_data, $list_id );
184
  }
185
-
186
- /**
187
- * Create contact list from product
188
- *
189
- * @param WC_Product $product Product object.
190
- *
191
- * @return int $list_id List ID.
192
- *
193
- * @since 4.4.3
194
- */
195
- public function create_list_from_product( $product ) {
196
-
197
- $list_id = 0;
198
-
199
- if( ! ( $product instanceof WC_Product ) ) {
200
- return $list_id;
201
- }
202
-
203
- $product_name = $product->get_name();
204
- $product_sku = $product->get_sku();
205
-
206
- $list_name = $product_name;
207
-
208
- if( empty( $product_sku ) ) {
209
- $list_slug = $product_name;
210
- } else {
211
- $list_slug = $product_sku;
212
- }
213
-
214
- $list = ES()->lists_db->get_list_by_slug( $list_slug );
215
- if( ! empty( $list ) ) {
216
- $list_id = $list['id'];
217
- } else {
218
- $list_id = ES()->lists_db->add_list( $list_name, $list_slug );
219
- }
220
-
221
- return $list_id;
222
- }
223
-
224
  }
46
  $list_field->set_options( $lists );
47
  $list_field->set_required();
48
  $this->add_field( $list_field );
 
 
 
49
  }
50
 
51
  /**
70
  }
71
  $data = $data_type->get_data( $data_item );
72
  $this->add_contact( $list_id, $data );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  }
74
  }
75
 
136
 
137
  do_action( 'ig_es_add_contact', $contact_data, $list_id );
138
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  }
lite/includes/workflows/admin/class-es-workflow-admin-ajax.php CHANGED
@@ -1,4 +1,9 @@
1
  <?php
 
 
 
 
 
2
  /**
3
  * Handles workflow admin ajax functionality
4
  *
1
  <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
  /**
8
  * Handles workflow admin ajax functionality
9
  *
lite/includes/workflows/admin/class-es-workflow-admin-edit.php CHANGED
@@ -153,6 +153,7 @@ class ES_Workflow_Admin_Edit {
153
  $action_status = 'error';
154
  }
155
  }
 
156
  $redirect_url = menu_page_url( 'es_workflows', false );
157
  $redirect_url = add_query_arg(
158
  array(
@@ -328,24 +329,26 @@ class ES_Workflow_Admin_Edit {
328
  * @since 4.4.1
329
  * @param int $workflow_id Workflow ID.
330
  * @return mixed $workflow_id/false workflow id on success otherwise false
 
 
331
  */
332
  public static function save( $workflow_id = 0 ) {
333
 
334
- $posted = ig_es_get_request_data( 'ig_es_workflow_data' );
335
 
336
  if ( ! is_array( $posted ) ) {
337
  return false;
338
  }
339
 
340
- $workflow_title = isset( $posted['title'] ) ? $posted['title'] : '';
341
  $workflow_name = ! empty( $workflow_title ) ? sanitize_title( ES_Clean::string( $workflow_title ) ) : '';
342
- $trigger_name = isset( $posted['trigger_name'] ) ? $posted['trigger_name'] : '';
343
- $trigger_options = isset( $posted['trigger_options'] ) ? $posted['trigger_options'] : array();
344
- $rules = isset( $posted['rules'] ) ? $posted['rules'] : array();
345
- $actions = isset( $posted['actions'] ) ? $posted['actions'] : array();
346
- $status = isset( $posted['status'] ) ? $posted['status'] : 0;
347
- $type = isset( $posted['type'] ) ? $posted['type'] : 0;
348
- $priority = isset( $posted['priority'] ) ? $posted['priority'] : 0;
349
 
350
  $workflow_meta = array();
351
  $workflow_meta['when_to_run'] = self::extract_string_option_value( 'when_to_run', $posted, 'immediately' );
153
  $action_status = 'error';
154
  }
155
  }
156
+
157
  $redirect_url = menu_page_url( 'es_workflows', false );
158
  $redirect_url = add_query_arg(
159
  array(
329
  * @since 4.4.1
330
  * @param int $workflow_id Workflow ID.
331
  * @return mixed $workflow_id/false workflow id on success otherwise false
332
+ *
333
+ * @modified 4.5.3 Removed sanitization for $posted being performed through ig_es_get_request_data function. Instead added individual sanitization based on workflow field.
334
  */
335
  public static function save( $workflow_id = 0 ) {
336
 
337
+ $posted = ig_es_get_request_data( 'ig_es_workflow_data', array(), false );
338
 
339
  if ( ! is_array( $posted ) ) {
340
  return false;
341
  }
342
 
343
+ $workflow_title = isset( $posted['title'] ) ? ig_es_clean( $posted['title'] ) : '';
344
  $workflow_name = ! empty( $workflow_title ) ? sanitize_title( ES_Clean::string( $workflow_title ) ) : '';
345
+ $trigger_name = isset( $posted['trigger_name'] ) ? ig_es_clean( $posted['trigger_name'] ): '';
346
+ $trigger_options = isset( $posted['trigger_options'] ) ? ig_es_clean( $posted['trigger_options'] ): array();
347
+ $rules = isset( $posted['rules'] ) ? ig_es_clean( $posted['rules'] ) : array();
348
+ $actions = isset( $posted['actions'] ) ? $posted['actions'] : array(); // We can't sanitize actions data since some actions like Send email allows html in its field.
349
+ $status = isset( $posted['status'] ) ? ig_es_clean( $posted['status'] ): 0;
350
+ $type = isset( $posted['type'] ) ? ig_es_clean( $posted['type'] ) : 0;
351
+ $priority = isset( $posted['priority'] ) ? ig_es_clean( $posted['priority'] ) : 0;
352
 
353
  $workflow_meta = array();
354
  $workflow_meta['when_to_run'] = self::extract_string_option_value( 'when_to_run', $posted, 'immediately' );
lite/includes/workflows/admin/class-es-workflow-admin.php CHANGED
@@ -1,4 +1,9 @@
1
  <?php
 
 
 
 
 
2
  /**
3
  * Workflow admin
4
  *
1
  <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
  /**
8
  * Workflow admin
9
  *
lite/includes/workflows/admin/views/action-fields.php CHANGED
@@ -71,6 +71,11 @@ foreach ( $fields as $field ) :
71
 
72
  <td class="ig-es-table__col ig-es-table__col--field ig-es-field-wrap">
73
  <?php $field->render( $value ); ?>
 
 
 
 
 
74
  </td>
75
  </tr>
76
 
71
 
72
  <td class="ig-es-table__col ig-es-table__col--field ig-es-field-wrap">
73
  <?php $field->render( $value ); ?>
74
+ <?php if ( $field->get_description() ): ?>
75
+ <p class="ig-es-field-description">
76
+ <?php echo $field->get_description(); ?>
77
+ </p>
78
+ <?php endif; ?>
79
  </td>
80
  </tr>
81
 
lite/includes/workflows/admin/views/trigger-fields.php CHANGED
@@ -29,8 +29,6 @@ if ( $fill_fields ) {
29
  }
30
 
31
  $fields = $trigger->get_fields();
32
-
33
-
34
  ?>
35
 
36
  <?php foreach( $fields as $field ):
@@ -69,5 +67,4 @@ $fields = $trigger->get_fields();
69
  <?php endif; ?>
70
  </td>
71
  </tr>
72
-
73
  <?php endforeach; ?>
29
  }
30
 
31
  $fields = $trigger->get_fields();
 
 
32
  ?>
33
 
34
  <?php foreach( $fields as $field ):
67
  <?php endif; ?>
68
  </td>
69
  </tr>
 
70
  <?php endforeach; ?>
lite/includes/workflows/class-es-clean.php CHANGED
@@ -129,4 +129,18 @@ class ES_Clean {
129
  return $data;
130
  }
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  }
129
  return $data;
130
  }
131
 
132
+ /**
133
+ * Performs a basic sanitize for editor content permitting all HTML.
134
+ *
135
+ * @param string $content
136
+ *
137
+ * @return string $content
138
+ *
139
+ * @since 4.5.3
140
+ */
141
+ public static function editor_content( $content ) {
142
+ $content = wp_check_invalid_utf8( stripslashes( (string) $content ) );
143
+ return $content;
144
+ }
145
+
146
  }
lite/includes/workflows/class-es-workflow.php CHANGED
@@ -298,13 +298,20 @@ class ES_Workflow {
298
  return false;
299
  }
300
 
 
301
  if ( ! $trigger->validate_workflow( $this ) ) {
302
  return false;
303
  }
304
-
 
305
  if ( ! apply_filters( 'ig_es_custom_validate_workflow', true, $this ) ) {
306
  return false;
307
  }
 
 
 
 
 
308
 
309
  return true;
310
  }
298
  return false;
299
  }
300
 
301
+
302
  if ( ! $trigger->validate_workflow( $this ) ) {
303
  return false;
304
  }
305
+
306
+ // Allow third party developers to hook their validation logic.
307
  if ( ! apply_filters( 'ig_es_custom_validate_workflow', true, $this ) ) {
308
  return false;
309
  }
310
+
311
+ // Validate a workflow based on the trigger being used in it.
312
+ if ( ! apply_filters( 'ig_es_validate_workflow_' . $trigger->name, true, $this ) ) {
313
+ return false;
314
+ }
315
 
316
  return true;
317
  }
lite/includes/workflows/fields/class-es-select.php CHANGED
@@ -233,7 +233,11 @@ class ES_Select extends ES_Field {
233
  </select>
234
 
235
  <script type="text/javascript">
236
- jQuery( 'body' ).trigger( 'wc-enhanced-select-init' );
 
 
 
 
237
  </script>
238
 
239
  <?php
233
  </select>
234
 
235
  <script type="text/javascript">
236
+ jQuery(document).ready(function(){
237
+ if( 'function' === typeof jQuery.fn.ig_es_select2 ) {
238
+ jQuery('.ig-es-form-multiselect[data-name="<?php echo esc_attr( $this->get_name() ); ?>"]').ig_es_select2();
239
+ }
240
+ });
241
  </script>
242
 
243
  <?php
lite/includes/workflows/fields/class-es-wp-editor.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Email Subscribers' WP Editor field
4
+ *
5
+ * @author Icegram
6
+ * @since 4.5.3
7
+ * @version 1.0
8
+ * @package Email Subscribers
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
+
15
+ /**
16
+ * Class for WP Editor field
17
+ *
18
+ * @class ES_WP_Editor
19
+ *
20
+ * @since 4.5.3
21
+ */
22
+ class ES_WP_Editor extends ES_Field {
23
+
24
+ protected $name = 'ig_es_wp_editor';
25
+
26
+ protected $type = 'textarea';
27
+
28
+ public function __construct() {
29
+ parent::__construct();
30
+ $this->set_title( __( 'WP Editor', 'email-subscribers' ) );
31
+ }
32
+
33
+ /**
34
+ * Render wp editor field
35
+ *
36
+ * @param string $value
37
+ *
38
+ * @since 4.5.3
39
+ */
40
+ public function render( $value ) {
41
+ $id = 'ig-es-wp-editor-' . uniqid();
42
+ $value = ES_Clean::editor_content( $value );
43
+
44
+ // If it is an ajax request then load wp editor using js library.
45
+ if ( is_ajax() ) {
46
+ ?>
47
+ <textarea name="<?php echo esc_attr( $this->get_full_name() ); ?>" id="<?php echo esc_attr( $id ); ?>">
48
+ </textarea>
49
+ <?php
50
+ $this->ajax_init( $id );
51
+ } else {
52
+ // If it is not an ajax request then load wp editor using Wordpress wp_editor PHP function.
53
+ wp_editor( $value, $id, [
54
+ 'textarea_name' => $this->get_full_name(),
55
+ 'tinymce' => true, // default to visual
56
+ 'quicktags' => true,
57
+ ]);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Initialize ajax loading of wp editor field
63
+ *
64
+ * @param int $id ID of the field.
65
+ *
66
+ * @since 4.5.3
67
+ */
68
+ public function ajax_init( $id ) {
69
+ ?>
70
+ <script type="text/javascript">
71
+ jQuery(document).ready(function(){
72
+ jQuery('#<?php echo esc_js( $id ); ?>').wp_js_editor();
73
+ });
74
+ </script>
75
+ <?php
76
+ }
77
+
78
+ /**
79
+ * Sanitizes the value of the field.
80
+ *
81
+ * @param string $value
82
+ *
83
+ * @return string
84
+ *
85
+ * @since 4.5.3
86
+ */
87
+ public function sanitize_value( $value ) {
88
+ return ES_Clean::editor_content( $value );
89
+ }
90
+ }
readme.txt CHANGED
@@ -6,7 +6,7 @@ Tags: email marketing, subscription, autoresponder, post notification, welcome e
6
  Requires at least: 3.9
7
  Tested up to: 5.4.2
8
  Requires PHP: 5.6
9
- Stable tag: 4.5.2
10
  License: GPLv3
11
  License URI: http://www.gnu.org/licenses
12
 
@@ -304,6 +304,13 @@ Refer [here](https://www.icegram.com/documentation/es-faq/).
304
 
305
  == Changelog ==
306
 
 
 
 
 
 
 
 
307
  **4.5.2 (23.07.2020)**
308
 
309
  * New: Added Seqeuence/ Autoresponder Reports
6
  Requires at least: 3.9
7
  Tested up to: 5.4.2
8
  Requires PHP: 5.6
9
+ Stable tag: 4.5.3
10
  License: GPLv3
11
  License URI: http://www.gnu.org/licenses
12
 
304
 
305
  == Changelog ==
306
 
307
+ **4.5.3 (30.07.2020)**
308
+
309
+ * New: Add Reply-To Email Address field for Broadcast
310
+ * New: Improve WooCommerce integration by adding more WooCommerce specific workflows [PRO]
311
+ * Update: Change Sequence Message status on change of parent status
312
+ * Fix: Load PRO email templates when upgrading from Free to PRO
313
+
314
  **4.5.2 (23.07.2020)**
315
 
316
  * New: Added Seqeuence/ Autoresponder Reports