Email Subscribers & Newsletters - Version 4.1.3

Version Description

(06.06.2019) = * New: Export contacts by list

Download this release

Release Info

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

Code changes from version 4.1.2.2 to 4.1.3

admin/class-email-subscribers-admin.php CHANGED
@@ -455,4 +455,17 @@ class Email_Subscribers_Admin {
455
  }
456
  }
457
 
 
 
 
 
 
 
 
 
 
 
 
 
 
458
  }
455
  }
456
  }
457
 
458
+ public function count_contacts_by_list() {
459
+
460
+ $list_id = ! empty( $_POST['list_id'] ) ? (int) $_POST['list_id'] : 0;
461
+
462
+ if ( $list_id == 0 ) {
463
+ return 0;
464
+ }
465
+
466
+ $total_count = ES_DB_Lists_Contacts::get_total_count_by_list( $list_id, 'all' );
467
+
468
+ die(json_encode(array('total' => $total_count)));
469
+ }
470
+
471
  }
admin/images/cf7-sync.png ADDED
Binary file
admin/js/email-subscribers-admin.js CHANGED
@@ -77,14 +77,14 @@
77
  success: function (response) {
78
  if (response && typeof response.status !== 'undefined' && response.status == "SUCCESS") {
79
  $('#es-send-test').parent().find('.helper').html('<span style="color:green">' + response.message + '</span>');
80
- }else{
81
  $('#es-send-test').parent().find('.helper').html('<span style="color:#e66060">' + response.message + '</span>');
82
  }
83
 
84
  $('#es-send-test').next('#spinner-image').hide();
85
  },
86
 
87
- error: function(err) {
88
  $('#es-send-test').next('#spinner-image').hide();
89
  }
90
  });
@@ -95,49 +95,76 @@
95
  });
96
 
97
  //klawoo form submit
98
- jQuery("form[name=klawoo_subscribe]").submit(function (e) {
99
- e.preventDefault();
100
- var form = e.target;
101
- jQuery(form).find('#klawoo_response').html('');
102
- jQuery(form).find('#klawoo_response').show();
103
-
104
- params = jQuery(form).serializeArray();
105
- params.push( {name: 'action', value: 'es_klawoo_subscribe' });
106
-
107
- jQuery.ajax({
108
- method: 'POST',
109
- type: 'text',
110
- url: ajaxurl,
111
- async: false,
112
- data: params,
113
- success: function(response) {
114
- if (response != '') {
115
- var parser = new DOMParser()
116
- var el = parser.parseFromString(response, "text/xml");
117
- var msg = el.childNodes[0].firstChild.nextElementSibling.innerHTML;
118
- if( jQuery(form).hasClass('es-onboarding')){
119
- location.reload();
120
- }else{
121
- jQuery(form).find('#klawoo_response').html();
122
-
123
- jQuery('.es-emm-optin #name').val('');
124
- jQuery('.es-emm-optin #email').val('');
125
- jQuery('.es-emm-optin #es-gdpr-agree').attr('checked', false);
126
- setTimeout(function() {
127
- jQuery(form).find('#klawoo_response').hide('slow');
128
- }, 2000);
129
- }
130
-
131
-
132
- } else {
133
- jQuery('#klawoo_response').html('error!');
134
- }
135
- }
136
- });
137
-
138
- });
139
 
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  });
142
 
143
 
77
  success: function (response) {
78
  if (response && typeof response.status !== 'undefined' && response.status == "SUCCESS") {
79
  $('#es-send-test').parent().find('.helper').html('<span style="color:green">' + response.message + '</span>');
80
+ } else {
81
  $('#es-send-test').parent().find('.helper').html('<span style="color:#e66060">' + response.message + '</span>');
82
  }
83
 
84
  $('#es-send-test').next('#spinner-image').hide();
85
  },
86
 
87
+ error: function (err) {
88
  $('#es-send-test').next('#spinner-image').hide();
89
  }
90
  });
95
  });
96
 
97
  //klawoo form submit
98
+ jQuery("form[name=klawoo_subscribe]").submit(function (e) {
99
+ e.preventDefault();
100
+ var form = e.target;
101
+ jQuery(form).find('#klawoo_response').html('');
102
+ jQuery(form).find('#klawoo_response').show();
103
+
104
+ params = jQuery(form).serializeArray();
105
+ params.push({name: 'action', value: 'es_klawoo_subscribe'});
106
+
107
+ jQuery.ajax({
108
+ method: 'POST',
109
+ type: 'text',
110
+ url: ajaxurl,
111
+ async: false,
112
+ data: params,
113
+ success: function (response) {
114
+ if (response != '') {
115
+ var parser = new DOMParser()
116
+ var el = parser.parseFromString(response, "text/xml");
117
+ var msg = el.childNodes[0].firstChild.nextElementSibling.innerHTML;
118
+ if (jQuery(form).hasClass('es-onboarding')) {
119
+ location.reload();
120
+ } else {
121
+ jQuery(form).find('#klawoo_response').html();
122
+
123
+ jQuery('.es-emm-optin #name').val('');
124
+ jQuery('.es-emm-optin #email').val('');
125
+ jQuery('.es-emm-optin #es-gdpr-agree').attr('checked', false);
126
+ setTimeout(function () {
127
+ jQuery(form).find('#klawoo_response').hide('slow');
128
+ }, 2000);
129
+ }
130
+
131
+
132
+ } else {
133
+ jQuery('#klawoo_response').html('error!');
134
+ }
135
+ }
136
+ });
137
+
138
+ });
139
 
140
 
141
+ var _href = $('#ig_es_export_link_select_list').attr("href");
142
+ // Select List ID for Export
143
+ $('#ig_es_export_list_dropdown').change(function () {
144
+ var selected_list_id = $(this).val();
145
+
146
+ $('#ig_es_export_link_select_list').attr("href", _href + '&list_id=' + selected_list_id);
147
+
148
+ // Update total count in lists
149
+ var params = {
150
+ action: 'count_contacts_by_list',
151
+ list_id: selected_list_id
152
+ };
153
+
154
+ $.ajax({
155
+ method: 'POST',
156
+ url: ajaxurl,
157
+ async: false,
158
+ data: params,
159
+ success: function (response) {
160
+ if (response != '') {
161
+ response = JSON.parse(response);
162
+ $('#ig_es_export_select_list .ig_es_total_contacts').text(response.total);
163
+ }
164
+ }
165
+ });
166
+
167
+ });
168
  });
169
 
170
 
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.1.2.2
7
  * Author: Icegram
8
  * Author URI: https://www.icegram.com/
9
  * Requires at least: 3.9
@@ -24,7 +24,7 @@ if ( ! defined( 'WPINC' ) ) {
24
  * Define constants
25
  */
26
  define( 'ES_PLUGIN_DIR', dirname( __FILE__ ) );
27
- define( 'ES_PLUGIN_VERSION', '4.1.2.2' );
28
  define( 'ES_PLUGIN_BASE_NAME', plugin_basename( __FILE__ ) );
29
 
30
  if ( ! defined( 'ES_PLUGIN_FILE' ) ) {
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.1.3
7
  * Author: Icegram
8
  * Author URI: https://www.icegram.com/
9
  * Requires at least: 3.9
24
  * Define constants
25
  */
26
  define( 'ES_PLUGIN_DIR', dirname( __FILE__ ) );
27
+ define( 'ES_PLUGIN_VERSION', '4.1.3' );
28
  define( 'ES_PLUGIN_BASE_NAME', plugin_basename( __FILE__ ) );
29
 
30
  if ( ! defined( 'ES_PLUGIN_FILE' ) ) {
includes/admin/class-es-admin-settings.php CHANGED
@@ -47,6 +47,9 @@ class ES_Admin_Settings {
47
  update_option( $key, stripslashes( $value ) );
48
  }
49
  }
 
 
 
50
  $message = __( 'Settings have been saved successfully!' );
51
  $status = 'success';
52
  ES_Common::show_message( $message, $status );
47
  update_option( $key, stripslashes( $value ) );
48
  }
49
  }
50
+
51
+ do_action('ig_es_after_settings_save', $options);
52
+
53
  $message = __( 'Settings have been saved successfully!' );
54
  $status = 'success';
55
  ES_Common::show_message( $message, $status );
includes/admin/class-es-export-subscribers.php CHANGED
@@ -17,9 +17,19 @@ class Export_Subscribers {
17
 
18
  if ( isset( $_GET['report'] ) && isset( $_GET['status'] ) ) {
19
 
20
- $status = trim( $_GET['status'] );
 
 
 
 
 
 
 
 
 
 
21
 
22
- $csv = $this->generate_csv( $status );
23
 
24
  $file_name = strtolower( $status ) . '-' . 'contacts.csv';
25
 
@@ -66,12 +76,17 @@ class Export_Subscribers {
66
 
67
  public function prepare_body() {
68
 
 
 
 
 
69
  $export_lists = array(
70
 
71
  'all' => __( 'All Contacts', 'email-subscribers' ),
72
  'active' => __( 'Subscribed Contacts', 'email-subscribers' ),
73
  'inactive' => __( 'Unsubscribed Contacts', 'email-subscribers' ),
74
  'unconfirmed' => __( 'Unconfirmed Contacts', 'email-subscribers' ),
 
75
  );
76
 
77
  $i = 1;
@@ -84,11 +99,11 @@ class Export_Subscribers {
84
 
85
  ?>
86
 
87
- <tr class="<?php echo $class; ?>">
88
  <td><?php echo $i; ?></td>
89
  <td><?php _e( $export_list, 'email-subscribers' ); ?></td>
90
- <td><?php echo $this->count_subscribers( $key ); ?></td>
91
- <td><a href="<?php echo $url; ?>"><?php _e( 'Download', 'email-subscribers' ); ?></a></td>
92
  </tr>
93
 
94
  <?php
@@ -165,7 +180,11 @@ class Export_Subscribers {
165
  break;
166
  }
167
 
168
- return $wpdb->get_var( $sql );
 
 
 
 
169
 
170
  }
171
 
@@ -206,7 +225,7 @@ class Export_Subscribers {
206
 
207
  }
208
 
209
- public function generate_csv( $status = 'all' ) {
210
 
211
  global $wpdb;
212
 
@@ -224,9 +243,31 @@ class Export_Subscribers {
224
  $query = "SELECT `first_name`, `last_name`, `email`, `status`, `unsubscribed`, `created_at` FROM $email_subscribe_table";
225
  } elseif ( 'unconfirmed' === $status ) {
226
  $query = "SELECT `first_name`, `last_name`, `email`, `status`, `unsubscribed`, `created_at` FROM $email_subscribe_table WHERE id IN (SELECT distinct(contact_id) FROM {$contact_lists_table} WHERE status = 'unconfirmed' )";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  }
228
 
229
- $subscribers = $wpdb->get_results( $query, ARRAY_A );
230
 
231
  $csv_output = '';
232
  if ( count( $subscribers ) > 0 ) {
@@ -238,22 +279,24 @@ class Export_Subscribers {
238
  __( 'Created On', 'email-subscribers' )
239
  );
240
 
241
- $csv_output .= implode( ',', $headers );
242
  $csv_output .= "\n";
243
 
244
  foreach ( $subscribers as $key => $subscriber ) {
245
 
246
- $data['name'] = trim( $subscriber['first_name'] . ' ' . $subscriber['last_name'] );
247
- $data['email'] = trim( $subscriber['email'] );
248
 
249
- if ( 'unconfirmed' === $status ) {
 
 
250
  $data['status'] = __( 'Unconfirmed', 'email-subscribers' );
251
  } else {
252
  $data['status'] = ( $subscriber['unsubscribed'] == 1 ) ? __( 'Unsubscribed', 'email-subscribers' ) : __( 'Subscribed', 'email-subscribers' );
253
  }
254
  $data['created_at'] = $subscriber['created_at'];
255
 
256
- $csv_output .= implode( ',', $data );
257
  $csv_output .= "\n";
258
  }
259
  }
17
 
18
  if ( isset( $_GET['report'] ) && isset( $_GET['status'] ) ) {
19
 
20
+ $status = trim( $_GET['status'] );
21
+ $selected_list_id = 0;
22
+
23
+ if ( 'select_list' === $status ) {
24
+ $selected_list_id = ! empty( $_GET['list_id'] ) ? $_GET['list_id'] : 0;
25
+ if ( 0 === $selected_list_id ) {
26
+ $message = __( "Please Select List", "email-subscribers" );
27
+ ES_Common::show_message( $message, 'error' );
28
+ exit();
29
+ }
30
+ }
31
 
32
+ $csv = $this->generate_csv( $status, $selected_list_id );
33
 
34
  $file_name = strtolower( $status ) . '-' . 'contacts.csv';
35
 
76
 
77
  public function prepare_body() {
78
 
79
+ $list_dropdown_html = "<select name='list_id' id='ig_es_export_list_dropdown'>";
80
+ $list_dropdown_html .= ES_Common::prepare_list_dropdown_options();
81
+ $list_dropdown_html .= "</select>";
82
+
83
  $export_lists = array(
84
 
85
  'all' => __( 'All Contacts', 'email-subscribers' ),
86
  'active' => __( 'Subscribed Contacts', 'email-subscribers' ),
87
  'inactive' => __( 'Unsubscribed Contacts', 'email-subscribers' ),
88
  'unconfirmed' => __( 'Unconfirmed Contacts', 'email-subscribers' ),
89
+ 'select_list' => $list_dropdown_html
90
  );
91
 
92
  $i = 1;
99
 
100
  ?>
101
 
102
+ <tr class="<?php echo $class; ?>" id="ig_es_export_<?php echo $key; ?>">
103
  <td><?php echo $i; ?></td>
104
  <td><?php _e( $export_list, 'email-subscribers' ); ?></td>
105
+ <td class="ig_es_total_contacts"><?php echo $this->count_subscribers( $key ); ?></td>
106
+ <td><a href="<?php echo $url; ?>" id="ig_es_export_link_<?php echo $key; ?>"><?php _e( 'Download', 'email-subscribers' ); ?></a></td>
107
  </tr>
108
 
109
  <?php
180
  break;
181
  }
182
 
183
+ if ( 'select_list' === $status ) {
184
+ return '-';
185
+ } else {
186
+ return $wpdb->get_var( $sql );
187
+ }
188
 
189
  }
190
 
225
 
226
  }
227
 
228
+ public function generate_csv( $status = 'all', $list_id = '' ) {
229
 
230
  global $wpdb;
231
 
243
  $query = "SELECT `first_name`, `last_name`, `email`, `status`, `unsubscribed`, `created_at` FROM $email_subscribe_table";
244
  } elseif ( 'unconfirmed' === $status ) {
245
  $query = "SELECT `first_name`, `last_name`, `email`, `status`, `unsubscribed`, `created_at` FROM $email_subscribe_table WHERE id IN (SELECT distinct(contact_id) FROM {$contact_lists_table} WHERE status = 'unconfirmed' )";
246
+ } elseif ( 'select_list' === $status ) {
247
+ $query = "SELECT `contact_id`, `status` FROM " . IG_LISTS_CONTACTS_TABLE . " WHERE list_id = %d ";
248
+ }
249
+
250
+ $subscribers = array();
251
+
252
+ if ( 'select_list' === $status ) {
253
+ $results = $wpdb->get_results( $wpdb->prepare( $query, $list_id ), ARRAY_A );
254
+
255
+ if ( count( $results ) > 0 ) {
256
+ $contact_id_status_map = array();
257
+ foreach ( $results as $result ) {
258
+ $contact_id_status_map[ $result['contact_id'] ] = $result['status'];
259
+ }
260
+
261
+ $contact_ids_str = "'" . implode( "' , '", array_keys( $contact_id_status_map ) ) . "' ";
262
+
263
+ $query = "SELECT `id`, `first_name`, `last_name`, `email`, `created_at` FROM {$email_subscribe_table} WHERE id IN ({$contact_ids_str})";
264
+ $subscribers = $wpdb->get_results( $query, ARRAY_A );
265
+ }
266
+
267
+ } else {
268
+ $subscribers = $wpdb->get_results( $query, ARRAY_A );
269
  }
270
 
 
271
 
272
  $csv_output = '';
273
  if ( count( $subscribers ) > 0 ) {
279
  __( 'Created On', 'email-subscribers' )
280
  );
281
 
282
+ $csv_output .= '"' . implode( '", "', $headers ) . '"';
283
  $csv_output .= "\n";
284
 
285
  foreach ( $subscribers as $key => $subscriber ) {
286
 
287
+ $data['name'] = str_replace('"', ' ', trim( $subscriber['first_name'] . ' ' . $subscriber['last_name'] ));
288
+ $data['email'] = str_replace('"', ' ', trim( $subscriber['email'] ));
289
 
290
+ if ( 'select_list' === $status ) {
291
+ $data['status'] = ucfirst( $contact_id_status_map[ $subscriber['id'] ] );
292
+ } elseif ( 'unconfirmed' === $status ) {
293
  $data['status'] = __( 'Unconfirmed', 'email-subscribers' );
294
  } else {
295
  $data['status'] = ( $subscriber['unsubscribed'] == 1 ) ? __( 'Unsubscribed', 'email-subscribers' ) : __( 'Subscribed', 'email-subscribers' );
296
  }
297
  $data['created_at'] = $subscriber['created_at'];
298
 
299
+ $csv_output .= '"' . implode( '", "', $data ) . '"';
300
  $csv_output .= "\n";
301
  }
302
  }
includes/admin/class-es-handle-sync-wp-user.php CHANGED
@@ -164,7 +164,6 @@ class ES_Handle_Sync_Wp_User {
164
  );
165
 
166
  $tabs = apply_filters( 'ig_es_sync_users_tabs', $tabs );
167
-
168
  ?>
169
  <h2 class="nav-tab-wrapper">
170
  <?php foreach ( $tabs as $key => $tab ) {
164
  );
165
 
166
  $tabs = apply_filters( 'ig_es_sync_users_tabs', $tabs );
 
167
  ?>
168
  <h2 class="nav-tab-wrapper">
169
  <?php foreach ( $tabs as $key => $tab ) {
includes/admin/class-es-lists-table.php CHANGED
@@ -304,11 +304,11 @@ class ES_Lists_Table extends WP_List_Table {
304
  $order_by_clause = '';
305
  $order = ! empty( $order ) ? ' ' . esc_sql( $order ) : ' DESC';
306
  $order_by_clause = ' ORDER BY ' . esc_sql( 'created_at' ) . ' ' . $order;
307
- $order_by_clause = ! empty( $order_by) ? $order_by_clause . ' , ' . esc_sql( $order_by ) . ' ' . $order : $order_by_clause;
308
 
309
- $sql .= $order_by_clause;
310
- $sql .= " LIMIT $per_page";
311
- $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
312
  $result = $wpdb->get_results( $sql, 'ARRAY_A' );
313
 
314
  } else {
@@ -362,19 +362,19 @@ class ES_Lists_Table extends WP_List_Table {
362
 
363
  switch ( $column_name ) {
364
  case 'active_contacts':
365
- $count = ES_DB_Lists_Contacts::get_total_count_by_list( $item['id'], 'active' );
366
- if($count > 0) {
367
- $url = admin_url('admin.php?page=es_subscribers&filter_by_status=subscribed&filter_by_list_id=' . $item['id']);
368
- $count = sprintf(__('<a href="%s" target="_blank">%d</a>', 'email-subscribers'), $url, $count);
369
- }
370
 
371
- return $count;
372
  break;
373
  case 'all_contacts':
374
  $count = ES_DB_Lists_Contacts::get_total_count_by_list( $item['id'], 'all' );
375
- if($count > 0) {
376
- $url = admin_url('admin.php?page=es_subscribers&filter_by_list_id=' . $item['id']);
377
- $count = sprintf(__('<a href="%s" target="_blank">%d</a>', 'email-subscribers'), $url, $count);
378
  }
379
 
380
  return $count;
@@ -382,6 +382,9 @@ class ES_Lists_Table extends WP_List_Table {
382
  case 'created_at':
383
  return ig_es_format_date_time( $item[ $column_name ] );
384
  break;
 
 
 
385
  default:
386
  return '';
387
  }
@@ -415,8 +418,8 @@ class ES_Lists_Table extends WP_List_Table {
415
  $actions = array();
416
  if ( $item['id'] != 1 ) {
417
  $actions = array(
418
- 'edit' => sprintf( __('<a href="?page=%s&action=%s&list=%s&_wpnonce=%s">Edit</a>', 'email-subscribers' ), esc_attr( Email_Subscribers::get_request( 'page' ) ), 'edit', absint( $item['id'] ), $list_nonce ),
419
- 'delete' => sprintf( __('<a href="?page=%s&action=%s&list=%s&_wpnonce=%s" onclick="return checkDelete()">Delete</a>', 'email-subscribers' ), esc_attr( Email_Subscribers::get_request( 'page' ) ), 'delete', absint( $item['id'] ), $list_nonce )
420
  );
421
  }
422
 
@@ -435,7 +438,8 @@ class ES_Lists_Table extends WP_List_Table {
435
  'name' => __( 'Name', 'email-subscribers' ),
436
  'active_contacts' => __( 'Active Contacts', 'email-subscribers' ),
437
  'all_contacts' => __( 'All Contacts', 'email-subscribers' ),
438
- 'created_at' => __( 'Created', 'email-subscribers' )
 
439
  );
440
 
441
  return $columns;
@@ -472,7 +476,7 @@ class ES_Lists_Table extends WP_List_Table {
472
  <p class="search-box">
473
  <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
474
  <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>"/>
475
- <?php submit_button( __('Search Lists', 'email-subscribers'), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
476
  </p>
477
  <?php }
478
 
@@ -582,4 +586,6 @@ class ES_Lists_Table extends WP_List_Table {
582
 
583
  return self::$instance;
584
  }
 
 
585
  }
304
  $order_by_clause = '';
305
  $order = ! empty( $order ) ? ' ' . esc_sql( $order ) : ' DESC';
306
  $order_by_clause = ' ORDER BY ' . esc_sql( 'created_at' ) . ' ' . $order;
307
+ $order_by_clause = ! empty( $order_by ) ? $order_by_clause . ' , ' . esc_sql( $order_by ) . ' ' . $order : $order_by_clause;
308
 
309
+ $sql .= $order_by_clause;
310
+ $sql .= " LIMIT $per_page";
311
+ $sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
312
  $result = $wpdb->get_results( $sql, 'ARRAY_A' );
313
 
314
  } else {
362
 
363
  switch ( $column_name ) {
364
  case 'active_contacts':
365
+ $count = ES_DB_Lists_Contacts::get_total_count_by_list( $item['id'], 'active' );
366
+ if ( $count > 0 ) {
367
+ $url = admin_url( 'admin.php?page=es_subscribers&filter_by_status=subscribed&filter_by_list_id=' . $item['id'] );
368
+ $count = sprintf( __( '<a href="%s" target="_blank">%d</a>', 'email-subscribers' ), $url, $count );
369
+ }
370
 
371
+ return $count;
372
  break;
373
  case 'all_contacts':
374
  $count = ES_DB_Lists_Contacts::get_total_count_by_list( $item['id'], 'all' );
375
+ if ( $count > 0 ) {
376
+ $url = admin_url( 'admin.php?page=es_subscribers&filter_by_list_id=' . $item['id'] );
377
+ $count = sprintf( __( '<a href="%s" target="_blank">%d</a>', 'email-subscribers' ), $url, $count );
378
  }
379
 
380
  return $count;
382
  case 'created_at':
383
  return ig_es_format_date_time( $item[ $column_name ] );
384
  break;
385
+
386
+ case 'export':
387
+ return "<a href='admin.php?page=download_report&report=users&status=select_list&list_id={$item['id']}'>" . __( 'Download', 'email-subscribers' ) . '</a>';
388
  default:
389
  return '';
390
  }
418
  $actions = array();
419
  if ( $item['id'] != 1 ) {
420
  $actions = array(
421
+ 'edit' => sprintf( __( '<a href="?page=%s&action=%s&list=%s&_wpnonce=%s">Edit</a>', 'email-subscribers' ), esc_attr( Email_Subscribers::get_request( 'page' ) ), 'edit', absint( $item['id'] ), $list_nonce ),
422
+ 'delete' => sprintf( __( '<a href="?page=%s&action=%s&list=%s&_wpnonce=%s" onclick="return checkDelete()">Delete</a>', 'email-subscribers' ), esc_attr( Email_Subscribers::get_request( 'page' ) ), 'delete', absint( $item['id'] ), $list_nonce )
423
  );
424
  }
425
 
438
  'name' => __( 'Name', 'email-subscribers' ),
439
  'active_contacts' => __( 'Active Contacts', 'email-subscribers' ),
440
  'all_contacts' => __( 'All Contacts', 'email-subscribers' ),
441
+ 'created_at' => __( 'Created', 'email-subscribers' ),
442
+ 'export' => __( 'Export', 'email-subscribers' )
443
  );
444
 
445
  return $columns;
476
  <p class="search-box">
477
  <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
478
  <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>"/>
479
+ <?php submit_button( __( 'Search Lists', 'email-subscribers' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
480
  </p>
481
  <?php }
482
 
586
 
587
  return self::$instance;
588
  }
589
+
590
+
591
  }
includes/class-email-subscribers.php CHANGED
@@ -92,9 +92,9 @@ class Email_Subscribers {
92
  $this->define_public_hooks();
93
 
94
 
95
- $ig_es_tracker = 'IG_Tracker_V_1_0_1';
96
  if ( is_admin() ) {
97
- $ig_es_feedback = new IG_Feedback_V_1_0_1( 'Email Subscribers', 'email-subscribers', 'ig_es', 'esfree.', false );
98
  $ig_es_feedback->render_deactivate_feedback();
99
  }
100
 
@@ -144,23 +144,6 @@ class Email_Subscribers {
144
  echo '<div class="notice notice-warning" style="background-color: #FFF;"><p style="letter-spacing: 0.6px;">' . $es_upgrade_text . '</p></div>';
145
  }
146
  }
147
-
148
- $all_plugins = $ig_es_tracker::get_plugins();
149
-
150
- if ( ! in_array( 'email-subscribers-premium/email-subscribers-premium.php', $all_plugins ) ) {
151
-
152
- // admin starter announcement
153
- $upsale_notice_option = get_option( 'ig_es_redirect_upsale_notice', 'no' );
154
- $dismiss_notice_option = get_option( 'ig_es_dismiss_upsale_notice', 'no' );
155
- if ( 'yes' !== $upsale_notice_option && 'yes' !== $dismiss_notice_option ) {
156
- $text_1 = __( 'Grow your audience. Stop worrying about email.' );
157
- echo '<div class="notice notice-warning" style="background: #ffefd5;">
158
- <p style="font-size: 1.1em; "><span class="dashicons dashicons-megaphone" style="color: #ff0000;"></span>&nbsp;&nbsp;' . $text_1 . '&nbsp;&nbsp;<strong><a href="?es_dismiss_admin_notice=1&option_name=redirect_upsale_notice" target="_blank" >' . __( 'Get Starter Plan', 'email-subscribers' ) . '</a></strong>
159
- <a style="float:right" class="ig-admin-btn ig-admin-btn-secondary" href="?es_dismiss_admin_notice=1&option_name=dismiss_upsale_notice">' . __( 'No, I don\'t want it', true ) . '</a>
160
- </p>
161
- </div>';
162
- }
163
- }
164
  //cron notice
165
  $notice_option = get_option( 'ig_es_wp_cron_notice' );
166
 
@@ -358,8 +341,8 @@ class Email_Subscribers {
358
  'includes/pro-features.php',
359
 
360
  // Feedback
361
- 'includes/feedback/class-ig-tracker-v-1-0-1.php',
362
- 'includes/feedback/class-ig-feedback-v-1-0-1.php',
363
  'includes/feedback.php'
364
  );
365
 
@@ -407,8 +390,10 @@ class Email_Subscribers {
407
  $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
408
  $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
409
  $this->loader->add_action( 'plugins_loaded', $plugin_admin, 'plugins_loaded' );
 
410
  $this->loader->add_filter( 'ig_es_lite_do_send', $plugin_admin, 'do_send', 10, 2 );
411
 
 
412
 
413
  //$this->loader->add_filter( 'ig_es_blocked_domains', $plugin_admin, 'blocked_domains', 10, 1 );
414
  //$this->loader->add_filter( 'ig_es_whitelist_ips', $plugin_admin, 'whitelist_ips', 10, 1 );
92
  $this->define_public_hooks();
93
 
94
 
95
+ $ig_es_tracker = 'IG_Tracker_V_1_0_2';
96
  if ( is_admin() ) {
97
+ $ig_es_feedback = new IG_Feedback_V_1_0_2( 'Email Subscribers', 'email-subscribers', 'ig_es', 'esfree.', false );
98
  $ig_es_feedback->render_deactivate_feedback();
99
  }
100
 
144
  echo '<div class="notice notice-warning" style="background-color: #FFF;"><p style="letter-spacing: 0.6px;">' . $es_upgrade_text . '</p></div>';
145
  }
146
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  //cron notice
148
  $notice_option = get_option( 'ig_es_wp_cron_notice' );
149
 
341
  'includes/pro-features.php',
342
 
343
  // Feedback
344
+ 'includes/feedback/class-ig-tracker-v-1-0-2.php',
345
+ 'includes/feedback/class-ig-feedback-v-1-0-2.php',
346
  'includes/feedback.php'
347
  );
348
 
390
  $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
391
  $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
392
  $this->loader->add_action( 'plugins_loaded', $plugin_admin, 'plugins_loaded' );
393
+
394
  $this->loader->add_filter( 'ig_es_lite_do_send', $plugin_admin, 'do_send', 10, 2 );
395
 
396
+ $this->loader->add_action( 'wp_ajax_count_contacts_by_list', $plugin_admin, 'count_contacts_by_list' );
397
 
398
  //$this->loader->add_filter( 'ig_es_blocked_domains', $plugin_admin, 'blocked_domains', 10, 1 );
399
  //$this->loader->add_filter( 'ig_es_whitelist_ips', $plugin_admin, 'whitelist_ips', 10, 1 );
includes/feedback/{class-ig-feedback-v-1-0-1.php → class-ig-feedback-v-1-0-2.php} RENAMED
@@ -5,16 +5,17 @@
5
  * The IG Feedback class adds functionality to get quick interactive feedback from users.
6
  * There are different types of feedabck widget like Stars, Emoji, Thubms Up/ Down, Number etc.
7
  *
8
- * @class IG_Feedback
9
  * @package feedback
10
  * @copyright Copyright (c) 2019, Icegram
11
  * @license https://opensource.org/licenses/gpl-license GNU Public License
 
12
  * @since 1.0.0
13
  */
14
 
15
  defined( 'ABSPATH' ) || exit;
16
 
17
- if ( ! class_exists( 'IG_Feedback_V_1_0_1' ) ) {
18
  /**
19
  * Icegram Deactivation Survey.
20
  *
@@ -26,7 +27,7 @@ if ( ! class_exists( 'IG_Feedback_V_1_0_1' ) ) {
26
  * @license GPL-2.0+
27
  * @copyright Copyright (c) 2019
28
  */
29
- class IG_Feedback_V_1_0_1 {
30
 
31
  /**
32
  * The API URL where we will send feedback data.
5
  * The IG Feedback class adds functionality to get quick interactive feedback from users.
6
  * There are different types of feedabck widget like Stars, Emoji, Thubms Up/ Down, Number etc.
7
  *
8
+ * @class IG_Feedback_V_1_0_2
9
  * @package feedback
10
  * @copyright Copyright (c) 2019, Icegram
11
  * @license https://opensource.org/licenses/gpl-license GNU Public License
12
+ * @author Icegram
13
  * @since 1.0.0
14
  */
15
 
16
  defined( 'ABSPATH' ) || exit;
17
 
18
+ if ( ! class_exists( 'IG_Feedback_V_1_0_2' ) ) {
19
  /**
20
  * Icegram Deactivation Survey.
21
  *
27
  * @license GPL-2.0+
28
  * @copyright Copyright (c) 2019
29
  */
30
+ class IG_Feedback_V_1_0_2 {
31
 
32
  /**
33
  * The API URL where we will send feedback data.
includes/feedback/{class-ig-tracker-v-1-0-1.php → class-ig-tracker-v-1-0-2.php} RENAMED
@@ -4,7 +4,7 @@ if ( ! defined( 'ABSPATH' ) ) {
4
  exit; // Exit if accessed directly.
5
  }
6
 
7
- if ( ! class_exists( 'IG_Tracker_V_1_0_1' ) ) {
8
 
9
  /**
10
  * Icegram tracker.
@@ -14,7 +14,7 @@ if ( ! class_exists( 'IG_Tracker_V_1_0_1' ) ) {
14
  *
15
  * @since 1.0.0
16
  */
17
- class IG_Tracker_V_1_0_1 {
18
 
19
  /**
20
  * Get Active, Inactive or all plugins info
@@ -30,6 +30,8 @@ if ( ! class_exists( 'IG_Tracker_V_1_0_1' ) ) {
30
  'inactive_plugins' => array()
31
  );
32
 
 
 
33
  if ( ! function_exists( 'get_plugins' ) ) {
34
  require_once ABSPATH . 'wp-admin/includes/plugin.php';
35
  }
@@ -71,8 +73,8 @@ if ( ! class_exists( 'IG_Tracker_V_1_0_1' ) ) {
71
  return $plugins['active_plugins'];
72
  } elseif ( 'inactive' === $status ) {
73
  return $plugins['inactive_plugins'];
74
- } elseif('all' === $status) {
75
- return array_merge($plugins['active_plugins'], $plugins['inactive_plugins']);
76
  }
77
  }
78
 
4
  exit; // Exit if accessed directly.
5
  }
6
 
7
+ if ( ! class_exists( 'IG_Tracker_V_1_0_2' ) ) {
8
 
9
  /**
10
  * Icegram tracker.
14
  *
15
  * @since 1.0.0
16
  */
17
+ class IG_Tracker_V_1_0_2 {
18
 
19
  /**
20
  * Get Active, Inactive or all plugins info
30
  'inactive_plugins' => array()
31
  );
32
 
33
+ // Check if get_plugins() function exists. This is required on the front end of the
34
+ // site, since it is in a file that is normally only loaded in the admin.
35
  if ( ! function_exists( 'get_plugins' ) ) {
36
  require_once ABSPATH . 'wp-admin/includes/plugin.php';
37
  }
73
  return $plugins['active_plugins'];
74
  } elseif ( 'inactive' === $status ) {
75
  return $plugins['inactive_plugins'];
76
+ } elseif ( 'all' === $status ) {
77
+ return array_merge( $plugins['active_plugins'], $plugins['inactive_plugins'] );
78
  }
79
  }
80
 
includes/pro-features.php CHANGED
@@ -7,6 +7,7 @@ add_filter( 'ig_es_sync_users_tabs', 'ig_es_add_sync_users_tabs', 11, 1 );
7
 
8
  add_action( 'ig_es_sync_users_tabs_comments', 'ig_es_add_comments_tab_settings' );
9
  add_action( 'ig_es_sync_users_tabs_woocommerce', 'ig_es_add_woocommerce_tab_settings' );
 
10
 
11
  function ig_es_add_upsale( $fields ) {
12
  global $ig_es_tracker;
@@ -45,8 +46,8 @@ function ig_es_add_sync_users_tabs( $tabs ) {
45
  $es_premium = 'email-subscribers-premium/email-subscribers-premium.php';
46
  $all_plugins = $ig_es_tracker::get_plugins();
47
 
 
48
  if ( ! in_array( $es_premium, $all_plugins ) ) {
49
-
50
  $tabs['comments'] = array(
51
  'name' => __( 'Comments', 'email-subscribers' ),
52
  'indicator_option' => 'ig_es_show_sync_comment_users_indicator',
@@ -55,8 +56,8 @@ function ig_es_add_sync_users_tabs( $tabs ) {
55
 
56
  $woocommerce_plugin = 'woocommerce/woocommerce.php';
57
 
 
58
  $active_plugins = $ig_es_tracker::get_active_plugins();
59
-
60
  if ( in_array( $woocommerce_plugin, $active_plugins ) ) {
61
  $tabs['woocommerce'] = array(
62
  'name' => __( 'WooCommerce', 'email-subscribers' ),
@@ -64,8 +65,17 @@ function ig_es_add_sync_users_tabs( $tabs ) {
64
  'indicator_label' => 'Starter'
65
  );
66
  }
67
- }
68
 
 
 
 
 
 
 
 
 
 
 
69
 
70
  return $tabs;
71
  }
@@ -87,13 +97,13 @@ function ig_es_add_comments_tab_settings( $tab_options ) {
87
  ob_start();
88
  ?>
89
  <div class="">
90
- <h2>Sync Comment Users</h2>
91
- <p>Quickly add to your mailing list when someone post a comment on your website.</p>
92
- <h2>How to setup?</h2>
93
- <p>Once you upgrade to <a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=comment_sync&utm_campaign=es_upsale#sync_comment_users">Email Subscribers Starter</a>, 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
94
- comment.</p>
95
  <hr>
96
- <p class="help">Checkout <a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=comment_sync&utm_campaign=es_upsale#sync_comment_users">Email Subscribers Starter</a> now</p>
97
  </div>
98
  <?php
99
 
@@ -116,14 +126,14 @@ function ig_es_add_woocommerce_tab_settings( $tab_options ) {
116
  ob_start();
117
  ?>
118
  <div class="">
119
- <h2>Sync WooCommerce Customers</h2>
120
- <p>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</p>
121
- <h2>How to setup?</h2>
122
- <p>Once you upgrade to <a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=woocommerce_sync&utm_campaign=es_upsale#sync_woocommerce_customers">Email Subscribers Starter</a>, 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
123
  purchase something
124
- from you.</p>
125
  <hr>
126
- <p class="help">Checkout <a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=woocommerce_sync&utm_campaign=es_upsale#sync_woocommerce_customers">Email Subscribers Starter</a> Now</p>
127
  </div>
128
  <?php $content = ob_get_clean(); ?>
129
 
@@ -140,4 +150,36 @@ function ig_es_add_woocommerce_tab_settings( $tab_options ) {
140
  <?php
141
  }
142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
7
 
8
  add_action( 'ig_es_sync_users_tabs_comments', 'ig_es_add_comments_tab_settings' );
9
  add_action( 'ig_es_sync_users_tabs_woocommerce', 'ig_es_add_woocommerce_tab_settings' );
10
+ add_action( 'ig_es_sync_users_tabs_cf7', 'ig_es_add_cf7_tab_settings' );
11
 
12
  function ig_es_add_upsale( $fields ) {
13
  global $ig_es_tracker;
46
  $es_premium = 'email-subscribers-premium/email-subscribers-premium.php';
47
  $all_plugins = $ig_es_tracker::get_plugins();
48
 
49
+ // Show integrations only if ES Premium is not installed.
50
  if ( ! in_array( $es_premium, $all_plugins ) ) {
 
51
  $tabs['comments'] = array(
52
  'name' => __( 'Comments', 'email-subscribers' ),
53
  'indicator_option' => 'ig_es_show_sync_comment_users_indicator',
56
 
57
  $woocommerce_plugin = 'woocommerce/woocommerce.php';
58
 
59
+ // Is WooCommmerce active? Show WooCommerce integration
60
  $active_plugins = $ig_es_tracker::get_active_plugins();
 
61
  if ( in_array( $woocommerce_plugin, $active_plugins ) ) {
62
  $tabs['woocommerce'] = array(
63
  'name' => __( 'WooCommerce', 'email-subscribers' ),
65
  'indicator_label' => 'Starter'
66
  );
67
  }
 
68
 
69
+ // Is Contact Form 7 active? Show CF7 integration.
70
+ $contact_form_7 = 'contact-form-7/wp-contact-form-7.php';
71
+ if ( in_array( $contact_form_7, $active_plugins ) ) {
72
+ $tabs['cf7'] = array(
73
+ 'name' => __( 'Contact Form 7', 'email-subscribers' ),
74
+ 'indicator_option' => 'ig_es_show_sync_cf7_users_indicator',
75
+ 'indicator_label' => 'Starter'
76
+ );
77
+ }
78
+ }
79
 
80
  return $tabs;
81
  }
97
  ob_start();
98
  ?>
99
  <div class="">
100
+ <h2><?php _e('Sync Comment Users', 'email-subscribers') ?></h2>
101
+ <p><?php _e('Quickly add to your mailing list when someone post a comment on your website.', 'email-subscribers') ?></p>
102
+ <h2><?php _e('How to setup?', 'email-subscribers') ?></h2>
103
+ <p><?php _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_upsale#sync_comment_users"><?php _e('Email Subscribers Starter', 'email-subscribers') ?></a>, <?php _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
104
+ comment.', 'email-subscribers') ?></p>
105
  <hr>
106
+ <p class="help"><?php _e('Checkout ', 'email-subscribers') ?><a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=comment_sync&utm_campaign=es_upsale#sync_comment_users"><?php _e('Email Subscribers Starter', 'email-subscribers') ?></a> <?php _e('now', 'email-subscribers') ?></p>
107
  </div>
108
  <?php
109
 
126
  ob_start();
127
  ?>
128
  <div class="">
129
+ <h2><?php _e('Sync WooCommerce Customers', 'email-subscribers') ?></h2>
130
+ <p><?php _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>
131
+ <h2><?php _e('How to setup?', 'email-subscribers') ?></h2>
132
+ <p><?php _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_upsale#sync_woocommerce_customers"><?php _e('Email Subscribers Starter', 'email-subscribers') ?></a>, <?php _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
133
  purchase something
134
+ from you.', 'email-subscribers') ?></p>
135
  <hr>
136
+ <p class="help"><?php _e('Checkout ', 'email-subscribers') ?><a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=woocommerce_sync&utm_campaign=es_upsale#sync_woocommerce_customers">Email Subscribers Starter</a> Now</p>
137
  </div>
138
  <?php $content = ob_get_clean(); ?>
139
 
150
  <?php
151
  }
152
 
153
+ function ig_es_add_cf7_tab_settings( $tab_options ) {
154
+
155
+ $info = array(
156
+ 'type' => 'info',
157
+ );
158
+
159
+ ob_start();
160
+ ?>
161
+ <div class="">
162
+ <h2><?php _e('Sync Contact Form 7 users', 'email-subscribers') ?></h2>
163
+ <p><?php _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>
164
+ <h2><?php _e('How to setup?', 'email-subscribers') ?></h2>
165
+ <p><?php _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_upsale#sync_cf7_subscribers"><?php _e('Email Subscribers Starter', 'email-subscribers') ?></a>, <?php _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>
166
+ <hr>
167
+ <p class="help"><?php _e('Checkout ', 'email-subscribers') ?><a href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=cf7_sync&utm_campaign=es_upsale#sync_cf7_subscribers">Email Subscribers Starter</a> Now</p>
168
+ </div>
169
+ <?php $content = ob_get_clean(); ?>
170
+
171
+ <a target="_blank" href="https://www.icegram.com/email-subscribers-starter/?utm_source=in_app&utm_medium=cf7_sync&utm_campaign=es_upsale#sync_cf7_subscribers">
172
+ <img src=" <?php echo EMAIL_SUBSCRIBERS_URL . '/admin/images/cf7-sync.png' ?> "/>
173
+ </a>
174
+
175
+ <?php
176
+
177
+ ES_Common::prepare_information_box( $info, $content );
178
+
179
+ ?>
180
+
181
+ <?php
182
+ }
183
+
184
+
185
 
readme.txt CHANGED
@@ -5,7 +5,7 @@ Author URI: https://www.icegram.com/
5
  Tags: subscription, newsletter, email marketing, post notification, email newsletter form, email signup, email widget, newsletter signup, subscribe, subscription form, bulk emails, signup form, list builder, lead generation, welcome email, contacts
6
  Requires at least: 3.9
7
  Tested up to: 5.2.1
8
- Stable tag: 4.1.2.2
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses
11
 
@@ -134,7 +134,11 @@ Check out [Email Subscribers Starter](https://www.icegram.com/email-subscribers-
134
 
135
  * **Automatic Background Sending**
136
 
137
- * **Connect with SMTP / Email Sending Services**
 
 
 
 
138
 
139
 
140
  **Get more benefits by using Email Subscribers with these free plugins**
@@ -301,6 +305,9 @@ Use our free plugin [Email Subscribers - Group Selector](https://wordpress.org/p
301
 
302
  == Changelog ==
303
 
 
 
 
304
  = 4.1.2.2 (31.05.2019) =
305
  * Fix: Fatal error: Call to undefined function get_plugins()
306
 
5
  Tags: subscription, newsletter, email marketing, post notification, email newsletter form, email signup, email widget, newsletter signup, subscribe, subscription form, bulk emails, signup form, list builder, lead generation, welcome email, contacts
6
  Requires at least: 3.9
7
  Tested up to: 5.2.1
8
+ Stable tag: 4.1.3
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses
11
 
134
 
135
  * **Automatic Background Sending**
136
 
137
+ * **Connect with SMTP / Email Sending Services**
138
+
139
+ * **Automatically add people to your mailing list whenever someone post a comment on your website**
140
+
141
+ * Integrate with **WooCommerce & Contact Form 7**
142
 
143
 
144
  **Get more benefits by using Email Subscribers with these free plugins**
305
 
306
  == Changelog ==
307
 
308
+ = 4.1.3 (06.06.2019) =
309
+ * New: Export contacts by list
310
+
311
  = 4.1.2.2 (31.05.2019) =
312
  * Fix: Fatal error: Call to undefined function get_plugins()
313