Booster for WooCommerce - Version 3.1.3

Version Description

  • 04/10/2017 =
  • Dev - PRICES & CURRENCIES - Global Discount - Admin settings descriptions updated.
  • Dev - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - Admin settings restyled; descriptions updated.
  • Dev - PRICES & CURRENCIES - Price Formats - Space not saving in thousand and decimal separator admin settings fields fixed.
  • Dev - PRICES & CURRENCIES - Price Formats - "Trim Zeros in Prices" option added.
  • Dev - PRICES & CURRENCIES - Price Formats - Price Formats by Currency (or WPML) - "Enable section" option added.
  • Dev - PRODUCTS - SKU - More Options - "Generate SKU for New Products Only on First Publish" option added.
  • Dev - PRODUCTS - SKU - Admin settings restyled.
  • Dev - SHIPPING & ORDERS - Order Custom Statuses - Admin settings descriptions updated.
  • Dev - EMAILS & MISC. - General - Coupons - "Generate Coupon Code Automatically" option added.
  • Dev - EMAILS & MISC. - URL Coupons - Admin settings descriptions updated.
  • Dev - EMAILS & MISC. - User Tracking - Initial module release (moved from "General" module).
  • Dev - Functions - User Roles - wcj_is_user_role() - super_admin added if checking for administrator.
  • Dev - Plugin update checker - "Check site key now" button added.
  • Dev - Plugin update checker - "Try again" links added.
  • Dev - Plugin update checker - Do not overwrite valid status with server error status.
  • Dev - wcj_full_pack filter added.
Download this release

Release Info

Developer algoritmika
Plugin Icon 128x128 Booster for WooCommerce
Version 3.1.3
Comparing to
See all releases

Code changes from version 3.1.2 to 3.1.3

includes/admin/class-wcj-settings-custom-fields.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings Custom Fields
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Settings_Custom_Fields {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 2.9.0
20
  * @since 2.8.0
21
  */
22
  function __construct() {
@@ -29,6 +29,17 @@ class WCJ_Settings_Custom_Fields {
29
  add_action( 'woocommerce_admin_field_custom_number', array( $this, 'output_custom_number' ) );
30
  add_action( 'woocommerce_admin_field_custom_link', array( $this, 'output_custom_link' ) );
31
  add_action( 'woocommerce_admin_field_module_tools', array( $this, 'output_module_tools' ) );
 
 
 
 
 
 
 
 
 
 
 
32
  }
33
 
34
  /**
2
  /**
3
  * Booster for WooCommerce - Settings Custom Fields
4
  *
5
+ * @version 3.1.3
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.1.3
20
  * @since 2.8.0
21
  */
22
  function __construct() {
29
  add_action( 'woocommerce_admin_field_custom_number', array( $this, 'output_custom_number' ) );
30
  add_action( 'woocommerce_admin_field_custom_link', array( $this, 'output_custom_link' ) );
31
  add_action( 'woocommerce_admin_field_module_tools', array( $this, 'output_module_tools' ) );
32
+ add_filter( 'woocommerce_admin_settings_sanitize_option', array( $this, 'maybe_unclean_field' ), PHP_INT_MAX, 3 );
33
+ }
34
+
35
+ /**
36
+ * maybe_unclean_field.
37
+ *
38
+ * @version 3.1.3
39
+ * @since 3.1.3
40
+ */
41
+ function maybe_unclean_field( $value, $option, $raw_value ) {
42
+ return ( isset( $option['wcj_raw'] ) && $option['wcj_raw'] ? $raw_value : $value );
43
  }
44
 
45
  /**
includes/admin/wcj-modules-cats.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Modules Array.
6
  *
7
- * @version 3.0.0
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  */
@@ -172,6 +172,7 @@ return apply_filters( 'wcj_modules', array(
172
  'wpml',
173
  'custom_css',
174
  'custom_js',
 
175
  'product_info',
176
  ),
177
  ),
4
  *
5
  * The WooCommerce Modules Array.
6
  *
7
+ * @version 3.1.3
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  */
172
  'wpml',
173
  'custom_css',
174
  'custom_js',
175
+ 'track_users',
176
  'product_info',
177
  ),
178
  ),
includes/class-wcj-general.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - General
4
  *
5
- * @version 2.9.1
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,11 @@ class WCJ_General extends WCJ_Module {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 2.9.1
 
 
 
 
19
  */
20
  function __construct() {
21
 
@@ -37,14 +41,6 @@ class WCJ_General extends WCJ_Module {
37
  ),
38
  ) );
39
 
40
- // By country scopes
41
- $this->track_users_scopes = array(
42
- '1' => __( 'Last 24 hours', 'woocommerce-jetpack' ),
43
- '7' => __( 'Last 7 days', 'woocommerce-jetpack' ),
44
- '28' => __( 'Last 28 days', 'woocommerce-jetpack' ),
45
- 'all_time' => __( 'All time', 'woocommerce-jetpack' ),
46
- );
47
-
48
  if ( $this->is_enabled() ) {
49
 
50
  // Recalculate cart totals
@@ -81,344 +77,65 @@ class WCJ_General extends WCJ_Module {
81
  add_action( 'init', array( $this, 'change_user_role_meta' ) );
82
  }
83
 
84
- // Track users
85
- if ( 'yes' === get_option( 'wcj_track_users_enabled', 'no' ) ) {
86
- // User tracking
87
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_track_users_script' ) );
88
- add_action( 'wp_ajax_' . 'wcj_track_users', array( $this, 'track_users' ) );
89
- add_action( 'wp_ajax_nopriv_' . 'wcj_track_users', array( $this, 'track_users' ) );
90
- // Stats in dashboard widgets
91
- if ( 'yes' === get_option( 'wcj_track_users_by_country_widget_enabled', 'yes' ) ) {
92
- add_action( 'wp_dashboard_setup', array( $this, 'add_track_users_dashboard_widgets' ) );
93
- add_action( 'admin_init', array( $this, 'maybe_delete_track_users_stats' ) );
94
- add_action( 'admin_init', array( $this, 'track_users_update_county_stats' ) );
95
- }
96
- // Order tracking
97
- if ( 'yes' === apply_filters( 'booster_get_option', 'no', get_option( 'wcj_track_users_save_order_http_referer_enabled', 'no' ) ) ) {
98
- add_action( 'woocommerce_new_order', array( $this, 'add_http_referer_to_order' ) );
99
- add_action( 'add_meta_boxes', array( $this, 'add_http_referer_order_meta_box' ) );
100
- }
101
- // Cron
102
- add_action( 'init', array( $this, 'track_users_schedule_the_event' ) );
103
- add_action( 'admin_init', array( $this, 'track_users_schedule_the_event' ) );
104
- add_action( 'wcj_track_users_generate_stats', array( $this, 'track_users_generate_stats_cron' ) );
105
  }
106
- }
107
- }
108
-
109
- /**
110
- * track_users_update_county_stats.
111
- *
112
- * @version 2.9.1
113
- * @since 2.9.1
114
- * @todo (maybe) `wp_nonce`
115
- */
116
- function track_users_update_county_stats() {
117
- if ( isset( $_GET['wcj_track_users_update_county_stats'] ) ) {
118
- $this->track_users_generate_stats_cron();
119
- wp_safe_redirect( remove_query_arg( 'wcj_track_users_update_county_stats' ) );
120
- exit;
121
- }
122
- }
123
-
124
- /**
125
- * track_users_schedule_the_event.
126
- *
127
- * @version 2.9.1
128
- * @since 2.9.1
129
- * @todo (maybe) customizable interval
130
- * @todo (maybe) separate events for all time, last 28 days, last 7 days, last 24 hours
131
- */
132
- function track_users_schedule_the_event() {
133
- $event_timestamp = wp_next_scheduled( 'wcj_track_users_generate_stats', array( 'hourly' ) );
134
- update_option( 'wcj_track_users_cron_time_schedule', $event_timestamp );
135
- if ( ! $event_timestamp ) {
136
- wp_schedule_event( time(), 'hourly', 'wcj_track_users_generate_stats', array( 'hourly' ) );
137
- }
138
- }
139
-
140
- /**
141
- * track_users_generate_stats_cron.
142
- *
143
- * @version 2.9.1
144
- * @since 2.9.1
145
- */
146
- function track_users_generate_stats_cron( $interval ) {
147
- update_option( 'wcj_track_users_cron_time_last_run', time() );
148
- $stats = get_option( 'wcj_track_users_stats_by_country', array() );
149
- foreach ( $this->track_users_scopes as $scope => $scope_title ) {
150
- $stats[ $scope ] = $this->generate_track_users_stats_by_country( $scope );
151
- }
152
- update_option( 'wcj_track_users_stats_by_country', $stats );
153
- }
154
-
155
- /**
156
- * add_http_referer_order_meta_box.
157
- *
158
- * @version 2.9.1
159
- * @since 2.9.1
160
- */
161
- function add_http_referer_order_meta_box() {
162
- add_meta_box(
163
- 'wc-jetpack-' . $this->id,
164
- __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Acquisition Source', 'woocommerce-jetpack' ),
165
- array( $this, 'create_http_referer_order_meta_box' ),
166
- 'shop_order',
167
- 'side',
168
- 'low'
169
- );
170
- }
171
-
172
- /**
173
- * get_referer_type.
174
- *
175
- * @version 2.9.1
176
- * @since 2.9.1
177
- * @todo this is not finished!
178
- */
179
- function get_referer_type( $http_referer ) {
180
- if ( '' != $http_referer && 'N/A' != $http_referer ) {
181
- if ( ( $http_referer_info = parse_url( $http_referer ) ) && isset( $http_referer_info['host'] ) ) {
182
- if ( false !== stripos( $http_referer_info['host'], 'google.' ) ) {
183
- return 'Google';
184
- } elseif ( false !== stripos( $http_referer_info['host'], 'wordpress.' ) ) {
185
- return 'WordPress';
186
- } elseif ( false !== stripos( $http_referer_info['host'], 'facebook.' ) ) {
187
- return 'Facebook';
188
- } else {
189
- return __( 'Other', 'woocommerce-jetpack' );
190
- }
191
- }
192
- }
193
- return 'N/A';
194
- }
195
-
196
- /**
197
- * create_http_referer_order_meta_box.
198
- *
199
- * @version 2.9.1
200
- * @since 2.9.1
201
- */
202
- function create_http_referer_order_meta_box() {
203
- if ( '' == ( $http_referer = get_post_meta( get_the_ID(), '_wcj_track_users_http_referer', true ) ) ) {
204
- $http_referer = 'N/A';
205
- }
206
- echo '<p>' . __( 'URL:', 'woocommerce-jetpack' ) . ' ' . $http_referer . '</p>';
207
- echo '<p>' . __( 'Type:', 'woocommerce-jetpack' ) . ' ' . $this->get_referer_type( $http_referer ) . '</p>';
208
- }
209
 
210
- /**
211
- * add_http_referer_to_order.
212
- *
213
- * @version 2.9.1
214
- * @since 2.9.1
215
- * @todo add "all orders by referer type" stats
216
- */
217
- function add_http_referer_to_order( $order_id ) {
218
- global $wpdb;
219
- $table_name = $wpdb->prefix . 'wcj_track_users';
220
- $http_referer = 'N/A';
221
- if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) === $table_name ) {
222
- $user_ip = ( class_exists( 'WC_Geolocation' ) ? WC_Geolocation::get_ip_address() : wcj_get_the_ip() );
223
- $result = $wpdb->get_row( "SELECT * FROM $table_name WHERE ip = '$user_ip' ORDER BY time DESC" );
224
- if ( $result ) {
225
- $http_referer = $result->referer;
226
- }
227
  }
228
- update_post_meta( $order_id, '_wcj_track_users_http_referer', $http_referer );
229
  }
230
 
231
  /**
232
- * maybe_delete_track_users_stats.
233
  *
234
- * @version 2.9.1
235
- * @since 2.9.1
236
- * @todo (maybe) wp_nonce
237
  */
238
- function maybe_delete_track_users_stats() {
239
- if ( isset( $_GET['wcj_delete_track_users_stats'] ) /* && is_super_admin() */ ) {
240
- global $wpdb;
241
- $table_name = $wpdb->prefix . 'wcj_track_users';
242
- $sql = "DROP TABLE IF EXISTS $table_name";
243
- $wpdb->query( $sql );
244
- delete_option( 'wcj_track_users_stats_by_country' );
245
- delete_option( 'wcj_track_users_cron_time_last_run' );
246
- wp_safe_redirect( remove_query_arg( 'wcj_delete_track_users_stats' ) );
247
- exit;
248
  }
249
  }
250
 
251
  /**
252
- * Add a widgets to the dashboard.
253
  *
254
- * @version 2.9.1
255
- * @since 2.9.1
 
256
  */
257
- function add_track_users_dashboard_widgets() {
258
- wp_add_dashboard_widget(
259
- 'wcj_track_users_dashboard_widget',
260
- __( 'Booster', 'woocommerce-jetpack' ) . ': ' . sprintf( __( 'Top %d countries by visits', 'woocommerce-jetpack' ),
261
- get_option( 'wcj_track_users_by_country_widget_top_count', 10 ) ),
262
- array( $this, 'track_users_by_country_dashboard_widget' )
263
- );
264
- }
265
-
266
- /**
267
- * get_saved_track_users_stats_by_country.
268
- *
269
- * @version 2.9.1
270
- * @since 2.9.1
271
- */
272
- function get_saved_track_users_stats_by_country( $scope ) {
273
- $stats = get_option( 'wcj_track_users_stats_by_country', array() );
274
- return ( isset( $stats[ $scope ] ) ? $stats[ $scope ] : array() );
275
- }
276
-
277
- /**
278
- * generate_track_users_stats_by_country.
279
- *
280
- * @version 2.9.1
281
- * @since 2.9.1
282
- */
283
- function generate_track_users_stats_by_country( $scope ) {
284
- global $wpdb;
285
- $table_name = $wpdb->prefix . 'wcj_track_users';
286
- switch ( $scope ) {
287
- case 'all_time':
288
- $select_query = "SELECT * FROM $table_name";
289
- break;
290
- default: // '28', '7', '1'
291
- $time_expired = date( 'Y-m-d H:i:s', ( current_time( 'timestamp' ) - $scope * 24 * 60 * 60 ) );
292
- $select_query = "SELECT * FROM $table_name WHERE time > '" . $time_expired . "'";
293
- break;
294
  }
295
- $totals = array();
296
- if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) === $table_name && ( $results = $wpdb->get_results( $select_query ) ) ) {
297
- foreach ( $results as $result ) {
298
- if ( ! isset( $totals[ $result->country ] ) ) {
299
- $totals[ $result->country ] = 1;
300
- } else {
301
- $totals[ $result->country ]++;
302
- }
303
- }
304
- arsort( $totals );
305
- }
306
- return $totals;
307
  }
308
 
309
  /**
310
- * track_users_by_country_dashboard_widget.
311
  *
312
- * @version 2.9.1
313
- * @since 2.9.1
314
- * @todo (maybe) display all info (IP, referer etc.) on country click
315
- * @todo (maybe) display stats by day and/or month
316
- * @todo (maybe) display stats by state
317
  */
318
- function track_users_by_country_dashboard_widget( $post, $args ) {
319
- $top_count = get_option( 'wcj_track_users_by_country_widget_top_count', 10 );
320
- foreach ( $this->track_users_scopes as $scope => $scope_title ) {
321
- if ( ! in_array( $scope, get_option( 'wcj_track_users_by_country_widget_scopes', array( '1', '28' ) ) ) ) {
322
- continue;
323
- }
324
- $totals = $this->get_saved_track_users_stats_by_country( $scope );
325
- if ( ! empty( $totals ) ) {
326
- $totals = array_slice( $totals, 0, $top_count );
327
- $table_data = array();
328
- $table_data[] = array( '', __( 'Country', 'woocommerce-jetpack' ), __( 'Visits', 'woocommerce-jetpack' ) );
329
- $i = 0;
330
- foreach ( $totals as $country_code => $visits ) {
331
- $i++;
332
- $country_info = ( '' != $country_code ? wcj_get_country_flag_by_code( $country_code ) . ' ' . wcj_get_country_name_by_code( $country_code ) : 'N/A' );
333
- $table_data[] = array( $i, $country_info, $visits );
334
- }
335
- echo '<strong>' . $scope_title . '</strong>';
336
- echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'horizontal' ) );
337
- } else {
338
- echo '<p>' . '<em>' . __( 'No stats yet.', 'woocommerce-jetpack' ) . '</em>' . '</p>';
339
  }
340
- }
341
- echo '<p>' .
342
- '<a class="button-primary" href="' . add_query_arg( 'wcj_delete_track_users_stats', '1' ) . '" ' .
343
- 'onclick="return confirm(\'' . __( 'Are you sure?', 'woocommerce-jetpack' ) . '\')"' .
344
- '>' . __( 'Delete all tracking data', 'woocommerce-jetpack' ) . '</a>' .
345
- '</p>';
346
- $cron_last_run = ( '' != ( $_time = get_option( 'wcj_track_users_cron_time_last_run', '' ) ) ? date( 'Y-m-d H:i:s', $_time ) : '-' );
347
- $cron_next_schedule = ( '' != ( $_time = get_option( 'wcj_track_users_cron_time_schedule', '' ) ) ? date( 'Y-m-d H:i:s', $_time ) : '-' );
348
- echo '<p>' .
349
- sprintf( __( 'Stats generated at %s. Next update is scheduled at %s.', 'woocommerce-jetpack' ), $cron_last_run, $cron_next_schedule ) . ' ' .
350
- '<a href="' . add_query_arg( 'wcj_track_users_update_county_stats', '1' ) . '">' . __( 'Update now', 'woocommerce-jetpack' ) . '</a>.' .
351
- '</p>';
352
- }
353
-
354
- /**
355
- * enqueue_track_users_script.
356
- *
357
- * @version 2.9.1
358
- * @since 2.9.1
359
- */
360
- function enqueue_track_users_script() {
361
- wp_enqueue_script( 'wcj-track-users', trailingslashit( wcj_plugin_url() ) . 'includes/js/wcj-track-users.js', array( 'jquery' ), WCJ()->version, true );
362
- wp_localize_script( 'wcj-track-users', 'track_users_ajax_object', array(
363
- 'ajax_url' => admin_url( 'admin-ajax.php' ),
364
- 'http_referer' => ( isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : 'N/A' ),
365
- 'user_ip' => ( class_exists( 'WC_Geolocation' ) ? WC_Geolocation::get_ip_address() : wcj_get_the_ip() ),
366
- ) );
367
- }
368
-
369
- /**
370
- * track_users.
371
- *
372
- * @version 2.9.1
373
- * @since 2.9.1
374
- * @todo (maybe) customizable `$time_expired`
375
- * @todo (maybe) optionally do not track selected user roles (e.g. admin)
376
- */
377
- function track_users() {
378
- if ( ! isset( $_POST['wcj_user_ip'] ) ) {
379
- die();
380
- }
381
- $user_ip = $_POST['wcj_user_ip'];
382
- global $wpdb;
383
- $table_name = $wpdb->prefix . 'wcj_track_users';
384
- if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) != $table_name ) {
385
- // Create DB table
386
- $charset_collate = $wpdb->get_charset_collate();
387
- $sql = "CREATE TABLE $table_name (
388
- id int NOT NULL AUTO_INCREMENT,
389
- time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
390
- country tinytext NOT NULL,
391
- state tinytext NOT NULL,
392
- ip text NOT NULL,
393
- referer text NOT NULL,
394
- PRIMARY KEY (id)
395
- ) $charset_collate;";
396
- require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
397
- dbDelta( $sql );
398
- } else {
399
- // Check if already tracked recently
400
- $time_expired = date( 'Y-m-d H:i:s', strtotime( '-1 day', current_time( 'timestamp' ) ) );
401
- $result = $wpdb->get_row( "SELECT * FROM $table_name WHERE ip = '$user_ip' AND time > '$time_expired'" );
402
- if ( $result ) {
403
- return;
404
  }
405
  }
406
- // Country by IP
407
- $location = ( class_exists( 'WC_Geolocation' ) ? WC_Geolocation::geolocate_ip( $user_ip ) : array( 'country' => '', 'state' => '' ) );
408
- // HTTP referrer
409
- $http_referer = ( isset( $_POST['wcj_http_referer'] ) ? $_POST['wcj_http_referer'] : 'N/A' );
410
- // Add row to DB table
411
- $wpdb->insert(
412
- $table_name,
413
- array(
414
- 'time' => current_time( 'mysql' ),
415
- 'country' => $location['country'],
416
- 'state' => $location['state'],
417
- 'ip' => $user_ip,
418
- 'referer' => $http_referer,
419
- )
420
- );
421
- die();
422
  }
423
 
424
  /**
2
  /**
3
  * Booster for WooCommerce - Module - General
4
  *
5
+ * @version 3.1.3
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.1.3
19
+ * @todo expand `$this->desc`
20
+ * @todo Coupon code generator - move to new module
21
+ * @todo Coupon code generator - add option to generate code only on button (in meta box) pressed
22
+ * @todo Coupon code generator - `wp_ajax_nopriv_wcj_generate_coupon_code` ?
23
  */
24
  function __construct() {
25
 
41
  ),
42
  ) );
43
 
 
 
 
 
 
 
 
 
44
  if ( $this->is_enabled() ) {
45
 
46
  // Recalculate cart totals
77
  add_action( 'init', array( $this, 'change_user_role_meta' ) );
78
  }
79
 
80
+ // Coupon code generator
81
+ if ( 'yes' === get_option( 'wcj_coupons_code_generator_enabled', 'no' ) ) {
82
+ add_action( 'wp_ajax_wcj_generate_coupon_code', array( $this, 'ajax_generate_coupon_code' ) );
83
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_generate_coupon_code_script' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  }
 
87
  }
88
 
89
  /**
90
+ * enqueue_generate_coupon_code_script.
91
  *
92
+ * @version 3.1.3
93
+ * @since 3.1.3
 
94
  */
95
+ function enqueue_generate_coupon_code_script() {
96
+ global $pagenow;
97
+ if ( 'post-new.php' === $pagenow && isset( $_GET['post_type'] ) && 'shop_coupon' === $_GET['post_type'] ) {
98
+ wp_enqueue_script( 'wcj-coupons-code-generator', wcj_plugin_url() . '/includes/js/wcj-coupons-code-generator.js', array( 'jquery' ), WCJ()->version, true );
99
+ wp_localize_script( 'wcj-coupons-code-generator', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
 
 
 
 
 
100
  }
101
  }
102
 
103
  /**
104
+ * generate_coupon_code.
105
  *
106
+ * @version 3.1.3
107
+ * @since 3.1.3
108
+ * @todo more options: "algorithm", "fixed length", "uppercase/lowercase" etc.
109
  */
110
+ function generate_coupon_code( $str = '' ) {
111
+ if ( '' === $str ) {
112
+ $str = time();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  }
114
+ return sprintf( '%08x', crc32( time() ) );
 
 
 
 
 
 
 
 
 
 
 
115
  }
116
 
117
  /**
118
+ * ajax_generate_coupon_code.
119
  *
120
+ * @version 3.1.3
121
+ * @since 3.1.3
122
+ * @todo (maybe) optionally generate some description for coupon (e.g. "Automatically generated coupon [YYYY-MM-DD]")
 
 
123
  */
124
+ function ajax_generate_coupon_code() {
125
+ $attempts = 0;
126
+ while ( true ) {
127
+ $coupon_code = $this->generate_coupon_code();
128
+ $coupon = new WC_Coupon( $coupon_code );
129
+ if ( ! $coupon->get_id() ) {
130
+ echo $coupon_code;
131
+ die();
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  }
133
+ $attempts++;
134
+ if ( $attempts > 100 ) { // shouldn't happen, but just in case...
135
+ echo '';
136
+ die();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  }
138
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  }
140
 
141
  /**
includes/class-wcj-price-formats.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Price Formats
4
  *
5
- * @version 2.8.0
6
  * @since 2.5.2
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,19 +16,26 @@ class WCJ_Price_Formats extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 2.8.0
20
  * @since 2.5.2
21
  */
22
  function __construct() {
23
 
24
  $this->id = 'price_formats';
25
  $this->short_desc = __( 'Price Formats', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Set different WooCommerce price formats for different currencies.', 'woocommerce-jetpack' );
27
  $this->link_slug = 'woocommerce-price-formats';
28
  parent::__construct();
29
 
30
  if ( $this->is_enabled() ) {
31
- add_filter( 'wc_price_args', array( $this, 'price_format' ), PHP_INT_MAX );
 
 
 
 
 
 
 
32
  }
33
  }
34
 
2
  /**
3
  * Booster for WooCommerce - Module - Price Formats
4
  *
5
+ * @version 3.1.3
6
  * @since 2.5.2
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.1.3
20
  * @since 2.5.2
21
  */
22
  function __construct() {
23
 
24
  $this->id = 'price_formats';
25
  $this->short_desc = __( 'Price Formats', 'woocommerce-jetpack' );
26
+ $this->desc = __( 'Set different WooCommerce price formats for different currencies. Set general price format options.', 'woocommerce-jetpack' );
27
  $this->link_slug = 'woocommerce-price-formats';
28
  parent::__construct();
29
 
30
  if ( $this->is_enabled() ) {
31
+ // Trim Zeros
32
+ if ( 'yes' === get_option( 'wcj_price_formats_general_trim_zeros', 'no' ) ) {
33
+ add_filter( 'woocommerce_price_trim_zeros', '__return_true', PHP_INT_MAX );
34
+ }
35
+ // Price Formats by Currency (or WPML)
36
+ if ( 'yes' === get_option( 'wcj_price_formats_by_currency_enabled', 'yes' ) ) {
37
+ add_filter( 'wc_price_args', array( $this, 'price_format' ), PHP_INT_MAX );
38
+ }
39
  }
40
  }
41
 
includes/class-wcj-sku.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - SKU
4
  *
5
- * @version 2.9.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,7 @@ class WCJ_SKU extends WCJ_Module {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 2.9.0
19
  */
20
  function __construct() {
21
 
@@ -23,8 +23,6 @@ class WCJ_SKU extends WCJ_Module {
23
  $this->short_desc = __( 'SKU', 'woocommerce-jetpack' );
24
  $this->desc = __( 'Generate WooCommerce SKUs automatically. Search by SKU on frontend.', 'woocommerce-jetpack' );
25
  $this->link_slug = 'woocommerce-sku';
26
- $this->extra_desc = __( 'When enabled - all new products will be given (autogenerated) SKU.', 'woocommerce-jetpack' ) . '<br>' .
27
- __( 'If you wish to set SKUs for existing products, use "Autogenerate SKUs" Tool.', 'woocommerce-jetpack' );
28
  parent::__construct();
29
 
30
  $this->add_tools( array(
@@ -300,13 +298,18 @@ class WCJ_SKU extends WCJ_Module {
300
  /**
301
  * set_sku_for_new_product.
302
  *
303
- * @version 2.9.0
 
304
  */
305
  function set_sku_for_new_product( $post_ID, $post, $update ) {
306
  if ( 'product' != $post->post_type ) {
307
  return;
308
  }
309
- if ( false === $update ) {
 
 
 
 
310
  $this->maybe_get_sequential_counters();
311
  $this->set_sku_with_variable( $post_ID, false );
312
  $this->maybe_save_sequential_counters();
2
  /**
3
  * Booster for WooCommerce - Module - SKU
4
  *
5
+ * @version 3.1.3
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.1.3
19
  */
20
  function __construct() {
21
 
23
  $this->short_desc = __( 'SKU', 'woocommerce-jetpack' );
24
  $this->desc = __( 'Generate WooCommerce SKUs automatically. Search by SKU on frontend.', 'woocommerce-jetpack' );
25
  $this->link_slug = 'woocommerce-sku';
 
 
26
  parent::__construct();
27
 
28
  $this->add_tools( array(
298
  /**
299
  * set_sku_for_new_product.
300
  *
301
+ * @version 3.1.3
302
+ * @todo (maybe) set `wcj_sku_new_products_generate_only_on_publish` to `yes` by default
303
  */
304
  function set_sku_for_new_product( $post_ID, $post, $update ) {
305
  if ( 'product' != $post->post_type ) {
306
  return;
307
  }
308
+ $do_generate_only_on_first_publish = ( 'yes' === get_option( 'wcj_sku_new_products_generate_only_on_publish', 'no' ) );
309
+ if (
310
+ ( false === $update && ! $do_generate_only_on_first_publish ) ||
311
+ ( $do_generate_only_on_first_publish && 'publish' === $post->post_status && '' == get_post_meta( $post_ID, '_sku', true ) )
312
+ ) {
313
  $this->maybe_get_sequential_counters();
314
  $this->set_sku_with_variable( $post_ID, false );
315
  $this->maybe_save_sequential_counters();
includes/class-wcj-track-users.php ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - User Tracking
4
+ *
5
+ * @version 3.1.3
6
+ * @since 3.1.3
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ if ( ! class_exists( 'WCJ_User_Tracking' ) ) :
13
+
14
+ class WCJ_User_Tracking extends WCJ_Module {
15
+
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @version 3.1.3
20
+ * @since 3.1.3
21
+ * @todo (maybe) if `wcj_track_users_enabled` set to `yes`, check if "General" module is also enabled (when upgrading from version 3.1.2)
22
+ */
23
+ function __construct() {
24
+
25
+ $this->id = 'track_users';
26
+ $this->short_desc = __( 'User Tracking', 'woocommerce-jetpack' );
27
+ $this->desc = __( 'Track your users in WooCommerce.', 'woocommerce-jetpack' );
28
+ $this->link_slug = 'woocommerce-user-tracking';
29
+ parent::__construct();
30
+
31
+ // By country scopes
32
+ $this->track_users_scopes = array(
33
+ '1' => __( 'Last 24 hours', 'woocommerce-jetpack' ),
34
+ '7' => __( 'Last 7 days', 'woocommerce-jetpack' ),
35
+ '28' => __( 'Last 28 days', 'woocommerce-jetpack' ),
36
+ 'all_time' => __( 'All time', 'woocommerce-jetpack' ),
37
+ );
38
+
39
+ if ( $this->is_enabled() ) {
40
+ // User tracking
41
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_track_users_script' ) );
42
+ add_action( 'wp_ajax_' . 'wcj_track_users', array( $this, 'track_users' ) );
43
+ add_action( 'wp_ajax_nopriv_' . 'wcj_track_users', array( $this, 'track_users' ) );
44
+ // Stats in dashboard widgets
45
+ if ( 'yes' === get_option( 'wcj_track_users_by_country_widget_enabled', 'yes' ) ) {
46
+ add_action( 'wp_dashboard_setup', array( $this, 'add_track_users_dashboard_widgets' ) );
47
+ add_action( 'admin_init', array( $this, 'maybe_delete_track_users_stats' ) );
48
+ add_action( 'admin_init', array( $this, 'track_users_update_county_stats' ) );
49
+ }
50
+ // Order tracking
51
+ if ( 'yes' === apply_filters( 'booster_get_option', 'no', get_option( 'wcj_track_users_save_order_http_referer_enabled', 'no' ) ) ) {
52
+ add_action( 'woocommerce_new_order', array( $this, 'add_http_referer_to_order' ) );
53
+ add_action( 'add_meta_boxes', array( $this, 'add_http_referer_order_meta_box' ) );
54
+ }
55
+ // Cron
56
+ add_action( 'init', array( $this, 'track_users_schedule_the_event' ) );
57
+ add_action( 'admin_init', array( $this, 'track_users_schedule_the_event' ) );
58
+ add_action( 'wcj_track_users_generate_stats', array( $this, 'track_users_generate_stats_cron' ) );
59
+ }
60
+ }
61
+
62
+ /**
63
+ * track_users_update_county_stats.
64
+ *
65
+ * @version 2.9.1
66
+ * @since 2.9.1
67
+ * @todo (maybe) `wp_nonce`
68
+ */
69
+ function track_users_update_county_stats() {
70
+ if ( isset( $_GET['wcj_track_users_update_county_stats'] ) ) {
71
+ $this->track_users_generate_stats_cron();
72
+ wp_safe_redirect( remove_query_arg( 'wcj_track_users_update_county_stats' ) );
73
+ exit;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * track_users_schedule_the_event.
79
+ *
80
+ * @version 2.9.1
81
+ * @since 2.9.1
82
+ * @todo (maybe) customizable interval
83
+ * @todo (maybe) separate events for all time, last 28 days, last 7 days, last 24 hours
84
+ */
85
+ function track_users_schedule_the_event() {
86
+ $event_timestamp = wp_next_scheduled( 'wcj_track_users_generate_stats', array( 'hourly' ) );
87
+ update_option( 'wcj_track_users_cron_time_schedule', $event_timestamp );
88
+ if ( ! $event_timestamp ) {
89
+ wp_schedule_event( time(), 'hourly', 'wcj_track_users_generate_stats', array( 'hourly' ) );
90
+ }
91
+ }
92
+
93
+ /**
94
+ * track_users_generate_stats_cron.
95
+ *
96
+ * @version 2.9.1
97
+ * @since 2.9.1
98
+ */
99
+ function track_users_generate_stats_cron( $interval ) {
100
+ update_option( 'wcj_track_users_cron_time_last_run', time() );
101
+ $stats = get_option( 'wcj_track_users_stats_by_country', array() );
102
+ foreach ( $this->track_users_scopes as $scope => $scope_title ) {
103
+ $stats[ $scope ] = $this->generate_track_users_stats_by_country( $scope );
104
+ }
105
+ update_option( 'wcj_track_users_stats_by_country', $stats );
106
+ }
107
+
108
+ /**
109
+ * add_http_referer_order_meta_box.
110
+ *
111
+ * @version 2.9.1
112
+ * @since 2.9.1
113
+ */
114
+ function add_http_referer_order_meta_box() {
115
+ add_meta_box(
116
+ 'wc-jetpack-' . $this->id,
117
+ __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Acquisition Source', 'woocommerce-jetpack' ),
118
+ array( $this, 'create_http_referer_order_meta_box' ),
119
+ 'shop_order',
120
+ 'side',
121
+ 'low'
122
+ );
123
+ }
124
+
125
+ /**
126
+ * get_referer_type.
127
+ *
128
+ * @version 2.9.1
129
+ * @since 2.9.1
130
+ * @todo this is not finished!
131
+ */
132
+ function get_referer_type( $http_referer ) {
133
+ if ( '' != $http_referer && 'N/A' != $http_referer ) {
134
+ if ( ( $http_referer_info = parse_url( $http_referer ) ) && isset( $http_referer_info['host'] ) ) {
135
+ if ( false !== stripos( $http_referer_info['host'], 'google.' ) ) {
136
+ return 'Google';
137
+ } elseif ( false !== stripos( $http_referer_info['host'], 'wordpress.' ) ) {
138
+ return 'WordPress';
139
+ } elseif ( false !== stripos( $http_referer_info['host'], 'facebook.' ) ) {
140
+ return 'Facebook';
141
+ } else {
142
+ return __( 'Other', 'woocommerce-jetpack' );
143
+ }
144
+ }
145
+ }
146
+ return 'N/A';
147
+ }
148
+
149
+ /**
150
+ * create_http_referer_order_meta_box.
151
+ *
152
+ * @version 2.9.1
153
+ * @since 2.9.1
154
+ */
155
+ function create_http_referer_order_meta_box() {
156
+ if ( '' == ( $http_referer = get_post_meta( get_the_ID(), '_wcj_track_users_http_referer', true ) ) ) {
157
+ $http_referer = 'N/A';
158
+ }
159
+ echo '<p>' . __( 'URL:', 'woocommerce-jetpack' ) . ' ' . $http_referer . '</p>';
160
+ echo '<p>' . __( 'Type:', 'woocommerce-jetpack' ) . ' ' . $this->get_referer_type( $http_referer ) . '</p>';
161
+ }
162
+
163
+ /**
164
+ * add_http_referer_to_order.
165
+ *
166
+ * @version 2.9.1
167
+ * @since 2.9.1
168
+ * @todo add "all orders by referer type" stats
169
+ */
170
+ function add_http_referer_to_order( $order_id ) {
171
+ global $wpdb;
172
+ $table_name = $wpdb->prefix . 'wcj_track_users';
173
+ $http_referer = 'N/A';
174
+ if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) === $table_name ) {
175
+ $user_ip = ( class_exists( 'WC_Geolocation' ) ? WC_Geolocation::get_ip_address() : wcj_get_the_ip() );
176
+ $result = $wpdb->get_row( "SELECT * FROM $table_name WHERE ip = '$user_ip' ORDER BY time DESC" );
177
+ if ( $result ) {
178
+ $http_referer = $result->referer;
179
+ }
180
+ }
181
+ update_post_meta( $order_id, '_wcj_track_users_http_referer', $http_referer );
182
+ }
183
+
184
+ /**
185
+ * maybe_delete_track_users_stats.
186
+ *
187
+ * @version 2.9.1
188
+ * @since 2.9.1
189
+ * @todo (maybe) wp_nonce
190
+ */
191
+ function maybe_delete_track_users_stats() {
192
+ if ( isset( $_GET['wcj_delete_track_users_stats'] ) /* && is_super_admin() */ ) {
193
+ global $wpdb;
194
+ $table_name = $wpdb->prefix . 'wcj_track_users';
195
+ $sql = "DROP TABLE IF EXISTS $table_name";
196
+ $wpdb->query( $sql );
197
+ delete_option( 'wcj_track_users_stats_by_country' );
198
+ delete_option( 'wcj_track_users_cron_time_last_run' );
199
+ wp_safe_redirect( remove_query_arg( 'wcj_delete_track_users_stats' ) );
200
+ exit;
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Add a widgets to the dashboard.
206
+ *
207
+ * @version 2.9.1
208
+ * @since 2.9.1
209
+ */
210
+ function add_track_users_dashboard_widgets() {
211
+ wp_add_dashboard_widget(
212
+ 'wcj_track_users_dashboard_widget',
213
+ __( 'Booster', 'woocommerce-jetpack' ) . ': ' . sprintf( __( 'Top %d countries by visits', 'woocommerce-jetpack' ),
214
+ get_option( 'wcj_track_users_by_country_widget_top_count', 10 ) ),
215
+ array( $this, 'track_users_by_country_dashboard_widget' )
216
+ );
217
+ }
218
+
219
+ /**
220
+ * get_saved_track_users_stats_by_country.
221
+ *
222
+ * @version 2.9.1
223
+ * @since 2.9.1
224
+ */
225
+ function get_saved_track_users_stats_by_country( $scope ) {
226
+ $stats = get_option( 'wcj_track_users_stats_by_country', array() );
227
+ return ( isset( $stats[ $scope ] ) ? $stats[ $scope ] : array() );
228
+ }
229
+
230
+ /**
231
+ * generate_track_users_stats_by_country.
232
+ *
233
+ * @version 2.9.1
234
+ * @since 2.9.1
235
+ */
236
+ function generate_track_users_stats_by_country( $scope ) {
237
+ global $wpdb;
238
+ $table_name = $wpdb->prefix . 'wcj_track_users';
239
+ switch ( $scope ) {
240
+ case 'all_time':
241
+ $select_query = "SELECT * FROM $table_name";
242
+ break;
243
+ default: // '28', '7', '1'
244
+ $time_expired = date( 'Y-m-d H:i:s', ( current_time( 'timestamp' ) - $scope * 24 * 60 * 60 ) );
245
+ $select_query = "SELECT * FROM $table_name WHERE time > '" . $time_expired . "'";
246
+ break;
247
+ }
248
+ $totals = array();
249
+ if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) === $table_name && ( $results = $wpdb->get_results( $select_query ) ) ) {
250
+ foreach ( $results as $result ) {
251
+ if ( ! isset( $totals[ $result->country ] ) ) {
252
+ $totals[ $result->country ] = 1;
253
+ } else {
254
+ $totals[ $result->country ]++;
255
+ }
256
+ }
257
+ arsort( $totals );
258
+ }
259
+ return $totals;
260
+ }
261
+
262
+ /**
263
+ * track_users_by_country_dashboard_widget.
264
+ *
265
+ * @version 2.9.1
266
+ * @since 2.9.1
267
+ * @todo (maybe) display all info (IP, referer etc.) on country click
268
+ * @todo (maybe) display stats by day and/or month
269
+ * @todo (maybe) display stats by state
270
+ */
271
+ function track_users_by_country_dashboard_widget( $post, $args ) {
272
+ $top_count = get_option( 'wcj_track_users_by_country_widget_top_count', 10 );
273
+ foreach ( $this->track_users_scopes as $scope => $scope_title ) {
274
+ if ( ! in_array( $scope, get_option( 'wcj_track_users_by_country_widget_scopes', array( '1', '28' ) ) ) ) {
275
+ continue;
276
+ }
277
+ $totals = $this->get_saved_track_users_stats_by_country( $scope );
278
+ if ( ! empty( $totals ) ) {
279
+ $totals = array_slice( $totals, 0, $top_count );
280
+ $table_data = array();
281
+ $table_data[] = array( '', __( 'Country', 'woocommerce-jetpack' ), __( 'Visits', 'woocommerce-jetpack' ) );
282
+ $i = 0;
283
+ foreach ( $totals as $country_code => $visits ) {
284
+ $i++;
285
+ $country_info = ( '' != $country_code ? wcj_get_country_flag_by_code( $country_code ) . ' ' . wcj_get_country_name_by_code( $country_code ) : 'N/A' );
286
+ $table_data[] = array( $i, $country_info, $visits );
287
+ }
288
+ echo '<strong>' . $scope_title . '</strong>';
289
+ echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'horizontal' ) );
290
+ } else {
291
+ echo '<p>' . '<em>' . __( 'No stats yet.', 'woocommerce-jetpack' ) . '</em>' . '</p>';
292
+ }
293
+ }
294
+ echo '<p>' .
295
+ '<a class="button-primary" href="' . add_query_arg( 'wcj_delete_track_users_stats', '1' ) . '" ' .
296
+ 'onclick="return confirm(\'' . __( 'Are you sure?', 'woocommerce-jetpack' ) . '\')"' .
297
+ '>' . __( 'Delete all tracking data', 'woocommerce-jetpack' ) . '</a>' .
298
+ '</p>';
299
+ $cron_last_run = ( '' != ( $_time = get_option( 'wcj_track_users_cron_time_last_run', '' ) ) ? date( 'Y-m-d H:i:s', $_time ) : '-' );
300
+ $cron_next_schedule = ( '' != ( $_time = get_option( 'wcj_track_users_cron_time_schedule', '' ) ) ? date( 'Y-m-d H:i:s', $_time ) : '-' );
301
+ echo '<p>' .
302
+ sprintf( __( 'Stats generated at %s. Next update is scheduled at %s.', 'woocommerce-jetpack' ), $cron_last_run, $cron_next_schedule ) . ' ' .
303
+ '<a href="' . add_query_arg( 'wcj_track_users_update_county_stats', '1' ) . '">' . __( 'Update now', 'woocommerce-jetpack' ) . '</a>.' .
304
+ '</p>';
305
+ }
306
+
307
+ /**
308
+ * enqueue_track_users_script.
309
+ *
310
+ * @version 2.9.1
311
+ * @since 2.9.1
312
+ */
313
+ function enqueue_track_users_script() {
314
+ wp_enqueue_script( 'wcj-track-users', trailingslashit( wcj_plugin_url() ) . 'includes/js/wcj-track-users.js', array( 'jquery' ), WCJ()->version, true );
315
+ wp_localize_script( 'wcj-track-users', 'track_users_ajax_object', array(
316
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
317
+ 'http_referer' => ( isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : 'N/A' ),
318
+ 'user_ip' => ( class_exists( 'WC_Geolocation' ) ? WC_Geolocation::get_ip_address() : wcj_get_the_ip() ),
319
+ ) );
320
+ }
321
+
322
+ /**
323
+ * track_users.
324
+ *
325
+ * @version 2.9.1
326
+ * @since 2.9.1
327
+ * @todo (maybe) customizable `$time_expired`
328
+ * @todo (maybe) optionally do not track selected user roles (e.g. admin)
329
+ */
330
+ function track_users() {
331
+ if ( ! isset( $_POST['wcj_user_ip'] ) ) {
332
+ die();
333
+ }
334
+ $user_ip = $_POST['wcj_user_ip'];
335
+ global $wpdb;
336
+ $table_name = $wpdb->prefix . 'wcj_track_users';
337
+ if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) != $table_name ) {
338
+ // Create DB table
339
+ $charset_collate = $wpdb->get_charset_collate();
340
+ $sql = "CREATE TABLE $table_name (
341
+ id int NOT NULL AUTO_INCREMENT,
342
+ time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
343
+ country tinytext NOT NULL,
344
+ state tinytext NOT NULL,
345
+ ip text NOT NULL,
346
+ referer text NOT NULL,
347
+ PRIMARY KEY (id)
348
+ ) $charset_collate;";
349
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
350
+ dbDelta( $sql );
351
+ } else {
352
+ // Check if already tracked recently
353
+ $time_expired = date( 'Y-m-d H:i:s', strtotime( '-1 day', current_time( 'timestamp' ) ) );
354
+ $result = $wpdb->get_row( "SELECT * FROM $table_name WHERE ip = '$user_ip' AND time > '$time_expired'" );
355
+ if ( $result ) {
356
+ return;
357
+ }
358
+ }
359
+ // Country by IP
360
+ $location = ( class_exists( 'WC_Geolocation' ) ? WC_Geolocation::geolocate_ip( $user_ip ) : array( 'country' => '', 'state' => '' ) );
361
+ // HTTP referrer
362
+ $http_referer = ( isset( $_POST['wcj_http_referer'] ) ? $_POST['wcj_http_referer'] : 'N/A' );
363
+ // Add row to DB table
364
+ $wpdb->insert(
365
+ $table_name,
366
+ array(
367
+ 'time' => current_time( 'mysql' ),
368
+ 'country' => $location['country'],
369
+ 'state' => $location['state'],
370
+ 'ip' => $user_ip,
371
+ 'referer' => $http_referer,
372
+ )
373
+ );
374
+ die();
375
+ }
376
+
377
+ }
378
+
379
+ endif;
380
+
381
+ return new WCJ_User_Tracking();
includes/functions/wcj-user-roles-functions.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - User Roles
4
  *
5
- * @version 2.9.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -133,12 +133,12 @@ if ( ! function_exists( 'wcj_is_user_role' ) ) {
133
  /**
134
  * wcj_is_user_role.
135
  *
136
- * @version 2.9.0
137
  * @since 2.5.0
138
  * @return bool
139
  */
140
  function wcj_is_user_role( $user_role, $user_id = 0 ) {
141
- $_user = ( 0 == $user_id ) ? wp_get_current_user() : get_user_by( 'id', $user_id );
142
  if ( ! isset( $_user->roles ) || empty( $_user->roles ) ) {
143
  $_user->roles = array( 'guest' );
144
  }
@@ -146,10 +146,25 @@ if ( ! function_exists( 'wcj_is_user_role' ) ) {
146
  return false;
147
  }
148
  if ( is_array( $user_role ) ) {
 
 
 
149
  $_intersect = array_intersect( $user_role, $_user->roles );
150
  return ( ! empty( $_intersect ) );
151
  } else {
152
- return ( in_array( $user_role, $_user->roles ) );
 
 
 
 
 
 
 
 
 
 
153
  }
 
 
154
  }
155
  }
2
  /**
3
  * Booster for WooCommerce - Functions - User Roles
4
  *
5
+ * @version 3.1.3
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
133
  /**
134
  * wcj_is_user_role.
135
  *
136
+ * @version 3.1.3
137
  * @since 2.5.0
138
  * @return bool
139
  */
140
  function wcj_is_user_role( $user_role, $user_id = 0 ) {
141
+ $_user = ( 0 == $user_id ? wp_get_current_user() : get_user_by( 'id', $user_id ) );
142
  if ( ! isset( $_user->roles ) || empty( $_user->roles ) ) {
143
  $_user->roles = array( 'guest' );
144
  }
146
  return false;
147
  }
148
  if ( is_array( $user_role ) ) {
149
+ if ( in_array( 'administrator', $user_role ) ) {
150
+ $user_role[] = 'super_admin';
151
+ }
152
  $_intersect = array_intersect( $user_role, $_user->roles );
153
  return ( ! empty( $_intersect ) );
154
  } else {
155
+ if ( 'administrator' == $user_role ) {
156
+ return ( in_array( 'administrator', $_user->roles ) || in_array( 'super_admin', $_user->roles ) );
157
+ } else {
158
+ return ( in_array( $user_role, $_user->roles ) );
159
+ }
160
+ }
161
+ /* if ( ! is_array( $user_role ) ) {
162
+ $user_role = array( $user_role );
163
+ }
164
+ if ( in_array( 'administrator', $user_role ) ) {
165
+ $user_role[] = 'super_admin';
166
  }
167
+ $_intersect = array_intersect( $user_role, $_user->roles );
168
+ return ( ! empty( $_intersect ) ); */
169
  }
170
  }
includes/js/wcj-coupons-code-generator.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * wcj-coupons-code-generator.
3
+ *
4
+ * @version 3.1.3
5
+ * @since 3.1.3
6
+ */
7
+
8
+ jQuery(document).ready(function() {
9
+ if ( '' === jQuery("#title").val() ) {
10
+ var data = {
11
+ 'action': 'wcj_generate_coupon_code',
12
+ };
13
+ jQuery.ajax({
14
+ type: "POST",
15
+ url: ajax_object.ajax_url,
16
+ data: data,
17
+ success: function(response) {
18
+ if ( '' !== response && '' === jQuery("#title").val() ) {
19
+ jQuery("#title").val(response);
20
+ jQuery("#title-prompt-text").html('');
21
+ }
22
+ },
23
+ });
24
+ }
25
+ });
includes/settings/wcj-settings-general.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - General
4
  *
5
- * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo add link to Booster's shortcodes list
@@ -218,53 +218,21 @@ $settings = array(
218
  'id' => 'wcj_general_user_role_changer_options',
219
  ),
220
  array(
221
- 'title' => __( 'Track Users Options', 'woocommerce-jetpack' ),
222
  'type' => 'title',
223
- 'id' => 'wcj_track_users_options',
224
  ),
225
  array(
226
- 'title' => __( 'Track Users', 'woocommerce-jetpack' ),
227
- 'desc' => '<strong>' . __( 'Enable section', 'woocommerce-jetpack' ) . '</strong>',
228
- 'id' => 'wcj_track_users_enabled',
229
- 'default' => 'no',
230
- 'type' => 'checkbox',
231
- ),
232
- array(
233
- 'title' => __( 'Countries by Visits', 'woocommerce-jetpack' ),
234
- 'desc' => __( 'Enable admin dashboard widget', 'woocommerce-jetpack' ),
235
- 'id' => 'wcj_track_users_by_country_widget_enabled',
236
- 'default' => 'yes',
237
- 'type' => 'checkbox',
238
- ),
239
- array(
240
- 'desc_tip' => __( 'Select which info show in admin dashboard widget.', 'woocommerce-jetpack' ),
241
- 'id' => 'wcj_track_users_by_country_widget_scopes',
242
- 'default' => array( '1', '28' ),
243
- 'type' => 'multiselect',
244
- 'class' => 'chosen_select',
245
- 'options' => $this->track_users_scopes,
246
- ),
247
- array(
248
- 'desc_tip' => __( 'Select which how many top countries to show.', 'woocommerce-jetpack' ),
249
- 'id' => 'wcj_track_users_by_country_widget_top_count',
250
- 'default' => 10,
251
- 'type' => 'number',
252
- 'custom_attributes' => ( array( 'min' => 0 ) ),
253
- ),
254
- array(
255
- 'title' => __( 'Track Orders', 'woocommerce-jetpack' ),
256
- 'desc_tip' => __( 'Save customer\'s acquisition source (i.e. HTTP referer) for orders.', 'woocommerce-jetpack' ) . ' ' .
257
- __( 'This will add "Booster: Acquisition Source" meta box to each order\'s edit page.', 'woocommerce-jetpack' ) . ' ' .
258
- apply_filters( 'booster_get_message', '', 'desc' ),
259
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
260
- 'id' => 'wcj_track_users_save_order_http_referer_enabled',
261
  'default' => 'no',
262
  'type' => 'checkbox',
263
- 'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
264
  ),
265
  array(
266
  'type' => 'sectionend',
267
- 'id' => 'wcj_track_users_options',
268
  ),
269
  /*
270
  array(
2
  /**
3
  * Booster for WooCommerce - Settings - General
4
  *
5
+ * @version 3.1.3
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo add link to Booster's shortcodes list
218
  'id' => 'wcj_general_user_role_changer_options',
219
  ),
220
  array(
221
+ 'title' => __( 'Coupons Options', 'woocommerce-jetpack' ),
222
  'type' => 'title',
223
+ 'id' => 'wcj_coupons_options',
224
  ),
225
  array(
226
+ 'title' => __( 'Generate Coupon Code Automatically', 'woocommerce-jetpack' ),
227
+ 'desc_tip' => __( 'When enabled, this will generate coupon code automatically when adding new coupon.', 'woocommerce-jetpack' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
229
+ 'id' => 'wcj_coupons_code_generator_enabled',
230
  'default' => 'no',
231
  'type' => 'checkbox',
 
232
  ),
233
  array(
234
  'type' => 'sectionend',
235
+ 'id' => 'wcj_coupons_options',
236
  ),
237
  /*
238
  array(
includes/settings/wcj-settings-global-discount.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Global Discount
4
  *
5
- * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -48,6 +48,7 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_glo
48
  ),
49
  array(
50
  'title' => __( 'Enabled', 'woocommerce-jetpack' ),
 
51
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
52
  'id' => 'wcj_global_discount_sale_enabled_' . $i,
53
  'default' => 'yes',
@@ -55,6 +56,7 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_glo
55
  ),
56
  array(
57
  'title' => __( 'Type', 'woocommerce-jetpack' ),
 
58
  'id' => 'wcj_global_discount_sale_coefficient_type_' . $i,
59
  'default' => 'percent',
60
  'type' => 'select',
@@ -73,6 +75,7 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_glo
73
  ),
74
  array(
75
  'title' => __( 'Product Scope', 'woocommerce-jetpack' ),
 
76
  'id' => 'wcj_global_discount_sale_product_scope_' . $i,
77
  'default' => 'all',
78
  'type' => 'select',
2
  /**
3
  * Booster for WooCommerce - Settings - Global Discount
4
  *
5
+ * @version 3.1.3
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
48
  ),
49
  array(
50
  'title' => __( 'Enabled', 'woocommerce-jetpack' ),
51
+ 'desc_tip' => __( 'Enabled/disables the discount group.', 'woocommerce-jetpack' ),
52
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
53
  'id' => 'wcj_global_discount_sale_enabled_' . $i,
54
  'default' => 'yes',
56
  ),
57
  array(
58
  'title' => __( 'Type', 'woocommerce-jetpack' ),
59
+ 'desc_tip' => __( 'Can be fixed or percent.', 'woocommerce-jetpack' ),
60
  'id' => 'wcj_global_discount_sale_coefficient_type_' . $i,
61
  'default' => 'percent',
62
  'type' => 'select',
75
  ),
76
  array(
77
  'title' => __( 'Product Scope', 'woocommerce-jetpack' ),
78
+ 'desc_tip' => __( 'Possible values: all products, only products that are already on sale, only products that are not on sale.', 'woocommerce-jetpack' ),
79
  'id' => 'wcj_global_discount_sale_product_scope_' . $i,
80
  'default' => 'all',
81
  'type' => 'select',
includes/settings/wcj-settings-multicurrency.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Multicurrency (Currency Switcher)
4
  *
5
- * @version 3.1.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo "pretty prices"
@@ -14,12 +14,13 @@ $currency_from = get_woocommerce_currency();
14
  $all_currencies = wcj_get_currencies_names_and_symbols();
15
  $settings = array(
16
  array(
17
- 'title' => __( 'Options', 'woocommerce-jetpack' ),
18
  'type' => 'title',
19
  'id' => 'wcj_multicurrency_options',
20
  ),
21
  array(
22
  'title' => __( 'Exchange Rates Updates', 'woocommerce-jetpack' ),
 
23
  'id' => 'wcj_multicurrency_exchange_rate_update_auto',
24
  'default' => 'manual',
25
  'type' => 'select',
@@ -36,13 +37,14 @@ $settings = array(
36
  array(
37
  'title' => __( 'Multicurrency on per Product Basis', 'woocommerce-jetpack' ),
38
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
39
- 'desc_tip' => __( 'This will add meta boxes in product edit.', 'woocommerce-jetpack' ),
40
  'id' => 'wcj_multicurrency_per_product_enabled',
41
  'default' => 'yes',
42
  'type' => 'checkbox',
43
  ),
44
  array(
45
  'title' => __( 'Revert Currency to Default on Checkout', 'woocommerce-jetpack' ),
 
46
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
47
  'id' => 'wcj_multicurrency_revert',
48
  'default' => 'no',
@@ -50,7 +52,7 @@ $settings = array(
50
  ),
51
  array(
52
  'title' => __( 'Rounding', 'woocommerce-jetpack' ),
53
- 'desc' => __( 'If using exchange rates, choose rounding here.', 'woocommerce-jetpack' ),
54
  'id' => 'wcj_multicurrency_rounding',
55
  'default' => 'no_round',
56
  'type' => 'select',
@@ -63,7 +65,7 @@ $settings = array(
63
  ),
64
  array(
65
  'title' => __( 'Rounding Precision', 'woocommerce-jetpack' ),
66
- 'desc' => __( 'If rounding enabled, set precision here.', 'woocommerce-jetpack' ),
67
  'id' => 'wcj_multicurrency_rounding_precision',
68
  'default' => absint( get_option( 'woocommerce_price_num_decimals', 2 ) ),
69
  'type' => 'number',
@@ -71,6 +73,7 @@ $settings = array(
71
  ),
72
  array(
73
  'title' => __( 'Currency Switcher Template', 'woocommerce-jetpack' ),
 
74
  'desc' => wcj_message_replaced_values( array( '%currency_name%', '%currency_symbol%', '%currency_code%' ) ),
75
  'id' => 'wcj_multicurrency_switcher_template',
76
  'default' => '%currency_name% (%currency_symbol%)',
@@ -98,6 +101,7 @@ $settings = array(
98
  ),
99
  array(
100
  'title' => __( 'Total Currencies', 'woocommerce-jetpack' ),
 
101
  'id' => 'wcj_multicurrency_total_number',
102
  'default' => 2,
103
  'type' => 'custom_number',
@@ -156,7 +160,7 @@ $settings = array_merge( $settings, array(
156
  ),
157
  array(
158
  'title' => __( 'Roles', 'woocommerce-jetpack' ),
159
- 'desc' => __( 'Save settings after you change this option. Leave blank to disable.', 'woocommerce-jetpack' ),
160
  'type' => 'multiselect',
161
  'id' => 'wcj_multicurrency_role_defaults_roles',
162
  'default' => '',
2
  /**
3
  * Booster for WooCommerce - Settings - Multicurrency (Currency Switcher)
4
  *
5
+ * @version 3.1.3
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo "pretty prices"
14
  $all_currencies = wcj_get_currencies_names_and_symbols();
15
  $settings = array(
16
  array(
17
+ 'title' => __( 'General Options', 'woocommerce-jetpack' ),
18
  'type' => 'title',
19
  'id' => 'wcj_multicurrency_options',
20
  ),
21
  array(
22
  'title' => __( 'Exchange Rates Updates', 'woocommerce-jetpack' ),
23
+ 'desc_tip' => __( 'Select how you want currency exchange rates to be updated. Possible options are: manually or automatically via Currency Exchange Rates module.', 'woocommerce-jetpack' ),
24
  'id' => 'wcj_multicurrency_exchange_rate_update_auto',
25
  'default' => 'manual',
26
  'type' => 'select',
37
  array(
38
  'title' => __( 'Multicurrency on per Product Basis', 'woocommerce-jetpack' ),
39
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
40
+ 'desc_tip' => __( 'If you enable this option, you will be able to enter prices for products in different currencies directly (i.e. without exchange rates). This will add meta boxes in product edit.', 'woocommerce-jetpack' ),
41
  'id' => 'wcj_multicurrency_per_product_enabled',
42
  'default' => 'yes',
43
  'type' => 'checkbox',
44
  ),
45
  array(
46
  'title' => __( 'Revert Currency to Default on Checkout', 'woocommerce-jetpack' ),
47
+ 'desc_tip' => __( 'Enable this if you want prices to revert back to your shop\'s default currency, when customer reaches the checkout page.', 'woocommerce-jetpack' ),
48
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
49
  'id' => 'wcj_multicurrency_revert',
50
  'default' => 'no',
52
  ),
53
  array(
54
  'title' => __( 'Rounding', 'woocommerce-jetpack' ),
55
+ 'desc_tip' => __( 'If using exchange rates, choose rounding here.', 'woocommerce-jetpack' ),
56
  'id' => 'wcj_multicurrency_rounding',
57
  'default' => 'no_round',
58
  'type' => 'select',
65
  ),
66
  array(
67
  'title' => __( 'Rounding Precision', 'woocommerce-jetpack' ),
68
+ 'desc_tip' => __( 'If rounding is enabled, set rounding precision here.', 'woocommerce-jetpack' ),
69
  'id' => 'wcj_multicurrency_rounding_precision',
70
  'default' => absint( get_option( 'woocommerce_price_num_decimals', 2 ) ),
71
  'type' => 'number',
73
  ),
74
  array(
75
  'title' => __( 'Currency Switcher Template', 'woocommerce-jetpack' ),
76
+ 'desc_tip' => __( 'Set how you want currency switcher to be displayed on frontend.', 'woocommerce-jetpack' ),
77
  'desc' => wcj_message_replaced_values( array( '%currency_name%', '%currency_symbol%', '%currency_code%' ) ),
78
  'id' => 'wcj_multicurrency_switcher_template',
79
  'default' => '%currency_name% (%currency_symbol%)',
101
  ),
102
  array(
103
  'title' => __( 'Total Currencies', 'woocommerce-jetpack' ),
104
+ 'desc_tip' => __( 'Press Save changes after setting this option, so new settings fields will be added.', 'woocommerce-jetpack' ),
105
  'id' => 'wcj_multicurrency_total_number',
106
  'default' => 2,
107
  'type' => 'custom_number',
160
  ),
161
  array(
162
  'title' => __( 'Roles', 'woocommerce-jetpack' ),
163
+ 'desc_tip' => __( 'Save settings after you change this option. Leave blank to disable.', 'woocommerce-jetpack' ),
164
  'type' => 'multiselect',
165
  'id' => 'wcj_multicurrency_role_defaults_roles',
166
  'default' => '',
includes/settings/wcj-settings-order-custom-statuses.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce Settings - Order Custom Statuses
4
  *
5
- * @version 3.1.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -27,6 +27,7 @@ return array(
27
  array(
28
  'title' => __( 'Add All Statuses to Admin Order Bulk Actions', 'woocommerce-jetpack' ),
29
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
 
30
  'id' => 'wcj_orders_custom_statuses_add_to_bulk_actions',
31
  'default' => 'yes',
32
  'type' => 'checkbox',
@@ -34,6 +35,7 @@ return array(
34
  array(
35
  'title' => __( 'Add Custom Statuses to Admin Reports', 'woocommerce-jetpack' ),
36
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
 
37
  'id' => 'wcj_orders_custom_statuses_add_to_reports',
38
  'default' => 'yes',
39
  'type' => 'checkbox',
@@ -41,10 +43,11 @@ return array(
41
  array(
42
  'title' => __( 'Make Custom Status Orders Editable', 'woocommerce-jetpack' ),
43
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
 
 
44
  'id' => 'wcj_orders_custom_statuses_is_order_editable',
45
  'default' => 'no',
46
  'type' => 'checkbox',
47
- 'desc_tip' => apply_filters( 'booster_get_message', '', 'desc' ),
48
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
49
  ),
50
  array(
@@ -65,18 +68,19 @@ return array(
65
  array(
66
  'title' => __( 'Add Custom Statuses to Admin Order List Action Buttons', 'woocommerce-jetpack' ),
67
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
 
 
68
  'id' => 'wcj_orders_custom_statuses_add_to_order_list_actions',
69
  'default' => 'no',
70
  'type' => 'checkbox',
71
- 'desc_tip' => apply_filters( 'booster_get_message', '', 'desc' ),
72
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
73
  ),
74
  array(
75
  'desc' => __( 'Enable Colors', 'woocommerce-jetpack' ),
 
76
  'id' => 'wcj_orders_custom_statuses_add_to_order_list_actions_colored',
77
  'default' => 'no',
78
  'type' => 'checkbox',
79
- 'desc_tip' => apply_filters( 'booster_get_message', '', 'desc' ),
80
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
81
  ),
82
  array(
2
  /**
3
  * Booster for WooCommerce Settings - Order Custom Statuses
4
  *
5
+ * @version 3.1.3
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
27
  array(
28
  'title' => __( 'Add All Statuses to Admin Order Bulk Actions', 'woocommerce-jetpack' ),
29
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
30
+ 'desc_tip' => __( 'If you wish to add custom statuses to admin Orders page bulk actions, enable the checkbox here.', 'woocommerce-jetpack' ),
31
  'id' => 'wcj_orders_custom_statuses_add_to_bulk_actions',
32
  'default' => 'yes',
33
  'type' => 'checkbox',
35
  array(
36
  'title' => __( 'Add Custom Statuses to Admin Reports', 'woocommerce-jetpack' ),
37
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
38
+ 'desc_tip' => __( 'If you wish to add custom statuses to admin reports, enable the checkbox here.', 'woocommerce-jetpack' ),
39
  'id' => 'wcj_orders_custom_statuses_add_to_reports',
40
  'default' => 'yes',
41
  'type' => 'checkbox',
43
  array(
44
  'title' => __( 'Make Custom Status Orders Editable', 'woocommerce-jetpack' ),
45
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
46
+ 'desc_tip' => __( 'By default orders with custom statuses are not editable (same like with standard WooCommerce Completed status). If you wish to make custom status orders editable, enable the checkbox here.', 'woocommerce-jetpack' ) . ' ' .
47
+ apply_filters( 'booster_get_message', '', 'desc' ),
48
  'id' => 'wcj_orders_custom_statuses_is_order_editable',
49
  'default' => 'no',
50
  'type' => 'checkbox',
 
51
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
52
  ),
53
  array(
68
  array(
69
  'title' => __( 'Add Custom Statuses to Admin Order List Action Buttons', 'woocommerce-jetpack' ),
70
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
71
+ 'desc_tip' => __( 'If you wish to add custom statuses buttons to the admin Orders page action buttons (Actions column), enable the checkbox here.', 'woocommerce-jetpack' ) . ' ' .
72
+ apply_filters( 'booster_get_message', '', 'desc' ),
73
  'id' => 'wcj_orders_custom_statuses_add_to_order_list_actions',
74
  'default' => 'no',
75
  'type' => 'checkbox',
 
76
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
77
  ),
78
  array(
79
  'desc' => __( 'Enable Colors', 'woocommerce-jetpack' ),
80
+ 'desc_tip' => __( 'Choose if you want the buttons to have colors.', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
81
  'id' => 'wcj_orders_custom_statuses_add_to_order_list_actions_colored',
82
  'default' => 'no',
83
  'type' => 'checkbox',
 
84
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
85
  ),
86
  array(
includes/settings/wcj-settings-price-formats.php CHANGED
@@ -2,19 +2,43 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Price Formats
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
 
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
  $settings = array(
13
  array(
14
- 'title' => __( 'Formats', 'woocommerce-jetpack' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  'type' => 'title',
16
  'id' => 'wcj_price_formats_options',
17
  ),
 
 
 
 
 
 
 
18
  array(
19
  'title' => __( 'Total Number', 'woocommerce-jetpack' ),
20
  'id' => 'wcj_price_formats_total_number',
@@ -58,6 +82,7 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_pri
58
  'default' => wc_get_price_thousand_separator(),
59
  'type' => 'text',
60
  'css' => 'width:300px;',
 
61
  ),
62
  array(
63
  'desc' => __( 'Decimal Separator', 'woocommerce-jetpack' ),
@@ -65,6 +90,7 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_pri
65
  'default' => wc_get_price_decimal_separator(),
66
  'type' => 'text',
67
  'css' => 'width:300px;',
 
68
  ),
69
  array(
70
  'desc' => __( 'Number of Decimals', 'woocommerce-jetpack' ),
2
  /**
3
  * Booster for WooCommerce - Settings - Price Formats
4
  *
5
+ * @version 3.1.3
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
+ * @todo (maybe) add `desc_tip` to `wcj_price_formats_general_trim_zeros`
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
12
 
13
  $settings = array(
14
  array(
15
+ 'title' => __( 'General Options', 'woocommerce-jetpack' ),
16
+ 'type' => 'title',
17
+ 'id' => 'wcj_price_formats_general_options',
18
+ ),
19
+ array(
20
+ 'title' => __( 'Trim Zeros in Prices', 'woocommerce-jetpack' ),
21
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
22
+ 'type' => 'checkbox',
23
+ 'id' => 'wcj_price_formats_general_trim_zeros',
24
+ 'default' => 'no',
25
+ ),
26
+ array(
27
+ 'type' => 'sectionend',
28
+ 'id' => 'wcj_price_formats_general_options',
29
+ ),
30
+ array(
31
+ 'title' => __( 'Price Formats by Currency (or WPML)', 'woocommerce-jetpack' ),
32
  'type' => 'title',
33
  'id' => 'wcj_price_formats_options',
34
  ),
35
+ array(
36
+ 'title' => __( 'Price Formats by Currency (or WPML)', 'woocommerce-jetpack' ),
37
+ 'desc' => '<strong>' . __( 'Enable section', 'woocommerce-jetpack' ) . '</strong>',
38
+ 'type' => 'checkbox',
39
+ 'id' => 'wcj_price_formats_by_currency_enabled',
40
+ 'default' => 'yes',
41
+ ),
42
  array(
43
  'title' => __( 'Total Number', 'woocommerce-jetpack' ),
44
  'id' => 'wcj_price_formats_total_number',
82
  'default' => wc_get_price_thousand_separator(),
83
  'type' => 'text',
84
  'css' => 'width:300px;',
85
+ 'wcj_raw' => true,
86
  ),
87
  array(
88
  'desc' => __( 'Decimal Separator', 'woocommerce-jetpack' ),
90
  'default' => wc_get_price_decimal_separator(),
91
  'type' => 'text',
92
  'css' => 'width:300px;',
93
+ 'wcj_raw' => true,
94
  ),
95
  array(
96
  'desc' => __( 'Number of Decimals', 'woocommerce-jetpack' ),
includes/settings/wcj-settings-sku.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - SKU
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo tags (check SKU plugin); template: '{category_prefix}{tag_prefix}{prefix}{sku_number}{suffix}{tag_suffix}{category_suffix}{variation_suffix}'
@@ -27,12 +27,14 @@ $settings = array(
27
  'sequential' => __( 'Sequential', 'woocommerce-jetpack' ),
28
  'hash_crc32' => __( 'Pseudorandom - Hash (max 10 digits)', 'woocommerce-jetpack' ),
29
  ),
30
- 'desc_tip' => __( 'Possible values: from product ID, sequential or pseudorandom.', 'woocommerce-jetpack' ),
 
31
  'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
32
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
33
  ),
34
  array(
35
  'title' => __( 'Sequential Number Generation - Counter', 'woocommerce-jetpack' ),
 
36
  'id' => 'wcj_sku_number_generation_sequential',
37
  'default' => 1,
38
  'type' => 'number',
@@ -44,34 +46,38 @@ $settings = array(
44
  ),
45
  array(
46
  'title' => __( 'Sequential Number Generation - By Category', 'woocommerce-jetpack' ),
 
47
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
48
  'id' => 'wcj_sku_number_generation_sequential_by_cat',
49
  'default' => 'no',
50
  'type' => 'checkbox',
51
- 'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
52
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
53
  ),
54
  array(
55
  'title' => __( 'Prefix', 'woocommerce-jetpack' ),
 
56
  'id' => 'wcj_sku_prefix',
57
  'default' => '',
58
  'type' => 'text',
59
  ),
60
  array(
61
  'title' => __( 'Minimum Number Length', 'woocommerce-jetpack' ),
 
62
  'id' => 'wcj_sku_minimum_number_length',
63
  'default' => 0,
64
  'type' => 'number',
65
  ),
66
  array(
67
  'title' => __( 'Suffix', 'woocommerce-jetpack' ),
 
68
  'id' => 'wcj_sku_suffix',
69
  'default' => '',
70
  'type' => 'text',
71
  ),
72
  array(
73
  'title' => __( 'Template', 'woocommerce-jetpack' ),
74
- 'desc' => __( 'Replaced values:', 'woocommerce-jetpack' ) . '{category_prefix}, {category_suffix}, {prefix}, {suffix}, {variation_suffix}, {sku_number}.',
 
75
  'id' => 'wcj_sku_template',
76
  'default' => '{category_prefix}{prefix}{sku_number}{suffix}{category_suffix}{variation_suffix}',
77
  'type' => 'text',
@@ -79,7 +85,8 @@ $settings = array(
79
  ),
80
  array(
81
  'title' => __( 'Variable Products Variations', 'woocommerce-jetpack' ),
82
- 'desc_tip' => __( 'Please note, that on new variable product creation, variations will get same SKUs as parent product, and if you want variations to have different SKUs, you will need to run "Autogenerate SKUs" tool manually.' ),
 
83
  'id' => 'wcj_sku_variations_handling',
84
  'default' => 'as_variable',
85
  'type' => 'select',
@@ -153,9 +160,18 @@ $settings = array_merge( $settings, array(
153
  'default' => 'yes',
154
  'type' => 'checkbox',
155
  ),
 
 
 
 
 
 
 
 
156
  array(
157
  'title' => __( 'Allow Duplicate SKUs', 'woocommerce-jetpack' ),
158
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
 
159
  'id' => 'wcj_sku_allow_duplicates_enabled',
160
  'default' => 'no',
161
  'type' => 'checkbox',
@@ -171,6 +187,7 @@ $settings = array_merge( $settings, array(
171
  array(
172
  'title' => __( 'Generate SKUs Only for Products with Empty SKU', 'woocommerce-jetpack' ),
173
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
 
174
  'id' => 'wcj_sku_generate_only_for_empty_sku',
175
  'default' => 'no',
176
  'type' => 'checkbox',
@@ -178,6 +195,7 @@ $settings = array_merge( $settings, array(
178
  array(
179
  'title' => __( 'Add SKU to Customer Emails', 'woocommerce-jetpack' ),
180
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
 
181
  'id' => 'wcj_sku_add_to_customer_emails',
182
  'default' => 'no',
183
  'type' => 'checkbox',
@@ -185,6 +203,7 @@ $settings = array_merge( $settings, array(
185
  array(
186
  'title' => __( 'Disable SKUs', 'woocommerce-jetpack' ),
187
  'desc' => __( 'Disable', 'woocommerce-jetpack' ),
 
188
  'id' => 'wcj_sku_disabled',
189
  'default' => 'no',
190
  'type' => 'checkbox',
2
  /**
3
  * Booster for WooCommerce - Settings - SKU
4
  *
5
+ * @version 3.1.3
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo tags (check SKU plugin); template: '{category_prefix}{tag_prefix}{prefix}{sku_number}{suffix}{tag_suffix}{category_suffix}{variation_suffix}'
27
  'sequential' => __( 'Sequential', 'woocommerce-jetpack' ),
28
  'hash_crc32' => __( 'Pseudorandom - Hash (max 10 digits)', 'woocommerce-jetpack' ),
29
  ),
30
+ 'desc_tip' => __( 'Number generation method.', 'woocommerce-jetpack' ) . ' ' .
31
+ __( 'Possible values: from product ID, sequential or pseudorandom.', 'woocommerce-jetpack' ),
32
  'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
33
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
34
  ),
35
  array(
36
  'title' => __( 'Sequential Number Generation - Counter', 'woocommerce-jetpack' ),
37
+ 'desc_tip' => __( 'If you choose to use sequential number inside SKU, you can set current sequential number counter here.', 'woocommerce-jetpack' ),
38
  'id' => 'wcj_sku_number_generation_sequential',
39
  'default' => 1,
40
  'type' => 'number',
46
  ),
47
  array(
48
  'title' => __( 'Sequential Number Generation - By Category', 'woocommerce-jetpack' ),
49
+ 'desc_tip' => __( 'Enables sequential number generation by category.', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
50
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
51
  'id' => 'wcj_sku_number_generation_sequential_by_cat',
52
  'default' => 'no',
53
  'type' => 'checkbox',
 
54
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
55
  ),
56
  array(
57
  'title' => __( 'Prefix', 'woocommerce-jetpack' ),
58
+ 'desc_tip' => __( 'SKU prefix.', 'woocommerce-jetpack' ),
59
  'id' => 'wcj_sku_prefix',
60
  'default' => '',
61
  'type' => 'text',
62
  ),
63
  array(
64
  'title' => __( 'Minimum Number Length', 'woocommerce-jetpack' ),
65
+ 'desc_tip' => __( 'Minimum length for SKU number part.', 'woocommerce-jetpack' ),
66
  'id' => 'wcj_sku_minimum_number_length',
67
  'default' => 0,
68
  'type' => 'number',
69
  ),
70
  array(
71
  'title' => __( 'Suffix', 'woocommerce-jetpack' ),
72
+ 'desc_tip' => __( 'SKU suffix.', 'woocommerce-jetpack' ),
73
  'id' => 'wcj_sku_suffix',
74
  'default' => '',
75
  'type' => 'text',
76
  ),
77
  array(
78
  'title' => __( 'Template', 'woocommerce-jetpack' ),
79
+ 'desc_tip' => __( 'SKU template.', 'woocommerce-jetpack' ),
80
+ 'desc' => wcj_message_replaced_values( array( '{category_prefix}', '{category_suffix}', '{prefix}', '{suffix}', '{variation_suffix}', '{sku_number}' ) ),
81
  'id' => 'wcj_sku_template',
82
  'default' => '{category_prefix}{prefix}{sku_number}{suffix}{category_suffix}{variation_suffix}',
83
  'type' => 'text',
85
  ),
86
  array(
87
  'title' => __( 'Variable Products Variations', 'woocommerce-jetpack' ),
88
+ 'desc_tip' => __( 'SKU generation for variations. Please note, that if "Generate SKU for New Products Only on First Publish" option below is not checked, then on new variable product creation, variations will get same SKUs as parent product, and if you want variations to have different SKUs, you will need to run "Autogenerate SKUs" tool manually.' ) . ' ' .
89
+ __( 'Possible values: SKU same as parent\'s product; Generate different SKU for each variation; SKU same as parent\'s product + variation letter suffix.', 'woocommerce-jetpack' ),
90
  'id' => 'wcj_sku_variations_handling',
91
  'default' => 'as_variable',
92
  'type' => 'select',
160
  'default' => 'yes',
161
  'type' => 'checkbox',
162
  ),
163
+ array(
164
+ 'title' => __( 'Generate SKU for New Products Only on First Publish', 'woocommerce-jetpack' ),
165
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
166
+ 'desc_tip' => __( 'This is important if, for example, you are using category prefix and don\'t want SKU generated too early, before you set the category.', 'woocommerce-jetpack' ),
167
+ 'id' => 'wcj_sku_new_products_generate_only_on_publish',
168
+ 'default' => 'no',
169
+ 'type' => 'checkbox',
170
+ ),
171
  array(
172
  'title' => __( 'Allow Duplicate SKUs', 'woocommerce-jetpack' ),
173
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
174
+ 'desc_tip' => __( 'If you wish to set SKUs manually, and you need to have same SKUs for different products, you can enable allow duplicate SKUs option here (which is disabled in WooCommerce by default).', 'woocommerce-jetpack' ),
175
  'id' => 'wcj_sku_allow_duplicates_enabled',
176
  'default' => 'no',
177
  'type' => 'checkbox',
187
  array(
188
  'title' => __( 'Generate SKUs Only for Products with Empty SKU', 'woocommerce-jetpack' ),
189
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
190
+ 'desc_tip' => __( 'This may help if you are going to use Autogenerate SKUs tool, but don\'t want to change your existing SKUs.', 'woocommerce-jetpack' ),
191
  'id' => 'wcj_sku_generate_only_for_empty_sku',
192
  'default' => 'no',
193
  'type' => 'checkbox',
195
  array(
196
  'title' => __( 'Add SKU to Customer Emails', 'woocommerce-jetpack' ),
197
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
198
+ 'desc_tip' => __( 'Adds product SKU to customer\'s emails.', 'woocommerce-jetpack' ),
199
  'id' => 'wcj_sku_add_to_customer_emails',
200
  'default' => 'no',
201
  'type' => 'checkbox',
203
  array(
204
  'title' => __( 'Disable SKUs', 'woocommerce-jetpack' ),
205
  'desc' => __( 'Disable', 'woocommerce-jetpack' ),
206
+ 'desc_tip' => __( 'Enable this option if you are not going to use SKUs in your shop at all.', 'woocommerce-jetpack' ),
207
  'id' => 'wcj_sku_disabled',
208
  'default' => 'no',
209
  'type' => 'checkbox',
includes/settings/wcj-settings-track-users.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Settings - User Tracking
4
+ *
5
+ * @version 3.1.3
6
+ * @since 3.1.3
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ return array(
13
+ array(
14
+ 'title' => __( 'Options', 'woocommerce-jetpack' ),
15
+ 'type' => 'title',
16
+ 'id' => 'wcj_track_users_general_options',
17
+ ),
18
+ array(
19
+ 'title' => __( 'Countries by Visits', 'woocommerce-jetpack' ),
20
+ 'desc' => __( 'Enable admin dashboard widget', 'woocommerce-jetpack' ),
21
+ 'id' => 'wcj_track_users_by_country_widget_enabled',
22
+ 'default' => 'yes',
23
+ 'type' => 'checkbox',
24
+ ),
25
+ array(
26
+ 'desc' => __( 'Info', 'woocommerce-jetpack' ),
27
+ 'desc_tip' => __( 'Select which info to show in admin dashboard widget.', 'woocommerce-jetpack' ),
28
+ 'id' => 'wcj_track_users_by_country_widget_scopes',
29
+ 'default' => array( '1', '28' ),
30
+ 'type' => 'multiselect',
31
+ 'class' => 'chosen_select',
32
+ 'options' => $this->track_users_scopes,
33
+ ),
34
+ array(
35
+ 'desc' => __( 'Top Countries', 'woocommerce-jetpack' ),
36
+ 'desc_tip' => __( 'Select how many top countries to show.', 'woocommerce-jetpack' ),
37
+ 'id' => 'wcj_track_users_by_country_widget_top_count',
38
+ 'default' => 10,
39
+ 'type' => 'number',
40
+ 'custom_attributes' => ( array( 'min' => 0 ) ),
41
+ ),
42
+ array(
43
+ 'title' => __( 'Track Orders', 'woocommerce-jetpack' ),
44
+ 'desc_tip' => __( 'Save customer\'s acquisition source (i.e. HTTP referer) for orders.', 'woocommerce-jetpack' ) . ' ' .
45
+ __( 'This will add "Booster: Acquisition Source" meta box to each order\'s edit page.', 'woocommerce-jetpack' ) . ' ' .
46
+ apply_filters( 'booster_get_message', '', 'desc' ),
47
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
48
+ 'id' => 'wcj_track_users_save_order_http_referer_enabled',
49
+ 'default' => 'no',
50
+ 'type' => 'checkbox',
51
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
52
+ ),
53
+ array(
54
+ 'type' => 'sectionend',
55
+ 'id' => 'wcj_track_users_general_options',
56
+ ),
57
+ );
includes/settings/wcj-settings-url-coupons.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - URL Coupons
4
  *
5
- * @version 2.9.1
6
  * @since 2.9.1
7
  * @author Algoritmika Ltd.
8
  */
@@ -43,6 +43,7 @@ $settings = array(
43
  ),
44
  array(
45
  'desc' => __( 'Custom Local URL', 'woocommerce-jetpack' ),
 
46
  'id' => 'wcj_url_coupons_redirect_custom_url',
47
  'default' => '',
48
  'type' => 'text',
2
  /**
3
  * Booster for WooCommerce - Settings - URL Coupons
4
  *
5
+ * @version 3.1.3
6
  * @since 2.9.1
7
  * @author Algoritmika Ltd.
8
  */
43
  ),
44
  array(
45
  'desc' => __( 'Custom Local URL', 'woocommerce-jetpack' ),
46
+ 'desc_tip' => __( 'If redirect to custom local URL is selected, set URL here.', 'woocommerce-jetpack' ),
47
  'id' => 'wcj_url_coupons_redirect_custom_url',
48
  'default' => '',
49
  'type' => 'text',
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: algoritmika,anbinder
3
  Tags: woocommerce,booster for woocommerce,woocommerce jetpack
4
  Requires at least: 4.4
5
  Tested up to: 4.8
6
- Stable tag: 3.1.2
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -26,7 +26,7 @@ Booster for WooCommerce is a WordPress plugin that supercharges your site with a
26
  * *Multicurrency (Currency Switcher)* - Add multiple currencies (currency switcher) to WooCommerce.
27
  * *Multicurrency Product Base Price* - Enter prices for WooCommerce products in different currencies.
28
  * *Offer Your Price* - Let your customers to suggest their price for products in WooCommerce.
29
- * *Price Formats* - Set different WooCommerce price formats for different currencies.
30
  * *Price by User Role* - Display WooCommerce products prices by user roles.
31
  * *Prices and Currencies by Country* - Change WooCommerce product price and currency automatically by customer's country.
32
  * *Product Open Pricing (Name Your Price)* - Let your WooCommerce store customers enter price for the product manually.
@@ -127,6 +127,7 @@ Booster for WooCommerce is a WordPress plugin that supercharges your site with a
127
  * *Old Slugs* - Remove old WooCommerce products slugs.
128
  * *Reports* - WooCommerce stock, sales, customers etc. reports.
129
  * *URL Coupons* - WooCommerce URL coupons.
 
130
 
131
  = Feedback =
132
  * We are open to your suggestions and feedback - thank you for using or trying out one of our plugins!
@@ -167,6 +168,24 @@ You can see the differences between versions in this [table](https://booster.io/
167
 
168
  == Changelog ==
169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  = 3.1.2 - 22/09/2017 =
171
  * Dev - WooCommerce v3.2 compatibility - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - `change_price_shipping()` - Taxes.
172
  * Dev - Shortcodes - Orders - `[wcj_order_items_table]` - `wcj_pdf_invoicing_cell_data` filter - `order` argument added.
3
  Tags: woocommerce,booster for woocommerce,woocommerce jetpack
4
  Requires at least: 4.4
5
  Tested up to: 4.8
6
+ Stable tag: 3.1.3
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
26
  * *Multicurrency (Currency Switcher)* - Add multiple currencies (currency switcher) to WooCommerce.
27
  * *Multicurrency Product Base Price* - Enter prices for WooCommerce products in different currencies.
28
  * *Offer Your Price* - Let your customers to suggest their price for products in WooCommerce.
29
+ * *Price Formats* - Set different WooCommerce price formats for different currencies. Set general price format options.
30
  * *Price by User Role* - Display WooCommerce products prices by user roles.
31
  * *Prices and Currencies by Country* - Change WooCommerce product price and currency automatically by customer's country.
32
  * *Product Open Pricing (Name Your Price)* - Let your WooCommerce store customers enter price for the product manually.
127
  * *Old Slugs* - Remove old WooCommerce products slugs.
128
  * *Reports* - WooCommerce stock, sales, customers etc. reports.
129
  * *URL Coupons* - WooCommerce URL coupons.
130
+ * *User Tracking* - Track your users in WooCommerce.
131
 
132
  = Feedback =
133
  * We are open to your suggestions and feedback - thank you for using or trying out one of our plugins!
168
 
169
  == Changelog ==
170
 
171
+ = 3.1.3 - 04/10/2017 =
172
+ * Dev - PRICES & CURRENCIES - Global Discount - Admin settings descriptions updated.
173
+ * Dev - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - Admin settings restyled; descriptions updated.
174
+ * Dev - PRICES & CURRENCIES - Price Formats - Space not saving in thousand and decimal separator admin settings fields fixed.
175
+ * Dev - PRICES & CURRENCIES - Price Formats - "Trim Zeros in Prices" option added.
176
+ * Dev - PRICES & CURRENCIES - Price Formats - Price Formats by Currency (or WPML) - "Enable section" option added.
177
+ * Dev - PRODUCTS - SKU - More Options - "Generate SKU for New Products Only on First Publish" option added.
178
+ * Dev - PRODUCTS - SKU - Admin settings restyled.
179
+ * Dev - SHIPPING & ORDERS - Order Custom Statuses - Admin settings descriptions updated.
180
+ * Dev - EMAILS & MISC. - General - Coupons - "Generate Coupon Code Automatically" option added.
181
+ * Dev - EMAILS & MISC. - URL Coupons - Admin settings descriptions updated.
182
+ * Dev - EMAILS & MISC. - User Tracking - Initial module release (moved from "General" module).
183
+ * Dev - Functions - User Roles - `wcj_is_user_role()` - `super_admin` added if checking for `administrator`.
184
+ * Dev - Plugin update checker - "Check site key now" button added.
185
+ * Dev - Plugin update checker - "Try again" links added.
186
+ * Dev - Plugin update checker - Do not overwrite valid status with server error status.
187
+ * Dev - `wcj_full_pack` filter added.
188
+
189
  = 3.1.2 - 22/09/2017 =
190
  * Dev - WooCommerce v3.2 compatibility - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - `change_price_shipping()` - Taxes.
191
  * Dev - Shortcodes - Orders - `[wcj_order_items_table]` - `wcj_pdf_invoicing_cell_data` filter - `order` argument added.
woocommerce-jetpack.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: https://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
- Version: 3.1.2
7
  Author: Algoritmika Ltd
8
  Author URI: https://booster.io
9
  Text Domain: woocommerce-jetpack
@@ -64,7 +64,7 @@ require_once( 'includes/constants/wcj-constants.php' );
64
  * Main WC_Jetpack Class
65
  *
66
  * @class WC_Jetpack
67
- * @version 3.1.1
68
  */
69
  final class WC_Jetpack {
70
 
@@ -74,7 +74,7 @@ final class WC_Jetpack {
74
  * @var string
75
  * @since 2.4.7
76
  */
77
- public $version = '3.1.2';
78
 
79
  /**
80
  * @var WC_Jetpack The single instance of the class
@@ -249,7 +249,7 @@ final class WC_Jetpack {
249
  /**
250
  * Include required core files used in admin and on the frontend.
251
  *
252
- * @version 3.1.0
253
  */
254
  function includes() {
255
 
@@ -263,7 +263,7 @@ final class WC_Jetpack {
263
  include_once( 'includes/classes/class-wcj-pdf-invoice.php' );
264
 
265
  // Plus
266
- if ( 'booster-plus-for-woocommerce.php' === basename( __FILE__ ) ) {
267
  require_once( 'includes/plus/class-wcj-plus.php' );
268
  }
269
 
@@ -333,7 +333,7 @@ final class WC_Jetpack {
333
  /**
334
  * Include modules and submodules
335
  *
336
- * @version 3.0.0
337
  */
338
  function include_modules() {
339
  $modules_files = array(
@@ -415,6 +415,7 @@ final class WC_Jetpack {
415
  'includes/class-wcj-currency-exchange-rates.php',
416
  'includes/class-wcj-price-formats.php',
417
  'includes/class-wcj-general.php',
 
418
  'includes/class-wcj-breadcrumbs.php',
419
  'includes/class-wcj-url-coupons.php',
420
  'includes/class-wcj-admin-bar.php',
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: https://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
+ Version: 3.1.3
7
  Author: Algoritmika Ltd
8
  Author URI: https://booster.io
9
  Text Domain: woocommerce-jetpack
64
  * Main WC_Jetpack Class
65
  *
66
  * @class WC_Jetpack
67
+ * @version 3.1.3
68
  */
69
  final class WC_Jetpack {
70
 
74
  * @var string
75
  * @since 2.4.7
76
  */
77
+ public $version = '3.1.3';
78
 
79
  /**
80
  * @var WC_Jetpack The single instance of the class
249
  /**
250
  * Include required core files used in admin and on the frontend.
251
  *
252
+ * @version 3.1.3
253
  */
254
  function includes() {
255
 
263
  include_once( 'includes/classes/class-wcj-pdf-invoice.php' );
264
 
265
  // Plus
266
+ if ( 'booster-plus-for-woocommerce.php' === basename( __FILE__ ) && apply_filters( 'wcj_full_pack', true ) ) {
267
  require_once( 'includes/plus/class-wcj-plus.php' );
268
  }
269
 
333
  /**
334
  * Include modules and submodules
335
  *
336
+ * @version 3.1.3
337
  */
338
  function include_modules() {
339
  $modules_files = array(
415
  'includes/class-wcj-currency-exchange-rates.php',
416
  'includes/class-wcj-price-formats.php',
417
  'includes/class-wcj-general.php',
418
+ 'includes/class-wcj-track-users.php',
419
  'includes/class-wcj-breadcrumbs.php',
420
  'includes/class-wcj-url-coupons.php',
421
  'includes/class-wcj-admin-bar.php',