Booster for WooCommerce - Version 2.5.4

Version Description

  • 19/07/2016 =
  • Fix - Manage Settings - Import - New line issue fixed.
  • Dev - Shortcodes - General - [wcj_country_select_drop_down_list] - replace_with_currency attribute added.
  • Dev - Shortcodes - Orders - [wcj_order_tax_by_class] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_total_by_tax_class] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_subtotal_by_tax_class] shortcode added.
  • Fix - Shortcodes - Products - Crowdfunding - get_product_orders_data() - WooCommerce loop fixed.
  • Fix - Shortcodes - Products - [wcj_product_time_since_last_sale] WooCommerce loop fixed.
  • Fix - Shortcodes - Products - [wcj_product_crowdfunding_time_remaining_progress_bar] fixed.
  • Fix - Shortcodes - Products - [wcj_product_crowdfunding_goal], [wcj_product_crowdfunding_goal_remaining], [wcj_product_total_orders_sum] fixed (and hide_currency attribute added).
  • Fix - Shortcodes - Products - [wcj_product_list_attributes] fixed.
  • Dev - Shortcodes - Products - [wcj_product_total_sales] - hide_if_zero and offset attributes added.
  • Dev - Shortcodes - Products - [wcj_product_time_since_last_sale] attributes added.
  • Dev - Shortcodes - Products - Crowdfunding - Code refactoring - moved to separate file.
  • Fix - PRICES & CURRENCIES - Prices and Currencies by Country - Getting customer_country_group_id on every get_customer_country_group_id() function call.
  • Dev - PRICES & CURRENCIES - Prices and Currencies by Country - add_hooks() function moved from init hook to constructor.
  • Dev - PRICES & CURRENCIES - Prices and Currencies by Country - "Add Flags Images to Select Drop-Down Box" option added ([wcj_country_select_drop_down_list] shortcode).
  • Dev - PRICES & CURRENCIES - Wholesale Price - "Products to exclude" option added.
  • Dev - PRODUCTS - Product by User - Messages options added.
  • Dev - PRODUCTS - Product by User - Fields ids; label tags added.
  • Dev - PRODUCTS - Product by User - Fields (all except Image field) refilled when validate returns false and after product successfully added.
  • Dev - PRODUCTS - Product by User - "Require Unique Title" option added.
  • Fix - EMAILS & MISC. - EU VAT Number - Started using WooCommerce customer set_is_vat_exempt() function.
  • Fix - EMAILS & MISC. - EU VAT Number - AJAX call fixed.
  • Dev - EMAILS & MISC. - Export - Initial module release (all tools moved from General module).
  • Dev - EMAILS & MISC. - General - Export Orders tool - Order number, status, item count, total, payment method, billing and shipping info columns added.
  • Tweak - Tags in plugin description and contributors changed.
Download this release

Release Info

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

Code changes from version 2.5.3 to 2.5.4

includes/admin/wcj-modules-cats.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Modules Array.
6
  *
7
- * @version 2.5.3
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  */
@@ -138,6 +138,7 @@ return array(
138
  'default_cat_id' => 'general',
139
  'all_cat_ids' => array(
140
  'general',
 
141
  // 'shortcodes',
142
  'eu_vat_number',
143
  'old_slugs',
4
  *
5
  * The WooCommerce Modules Array.
6
  *
7
+ * @version 2.5.4
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  */
138
  'default_cat_id' => 'general',
139
  'all_cat_ids' => array(
140
  'general',
141
+ 'export',
142
  // 'shortcodes',
143
  'eu_vat_number',
144
  'old_slugs',
includes/class-wcj-eu-vat-number.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack EU VAT Number class.
6
  *
7
- * @version 2.5.2
8
  * @since 2.3.9
9
  * @author Algoritmika Ltd.
10
  */
@@ -18,7 +18,7 @@ class WCJ_EU_VAT_Number extends WCJ_Module {
18
  /**
19
  * Constructor.
20
  *
21
- * @version 2.5.2
22
  */
23
  function __construct() {
24
 
@@ -44,9 +44,12 @@ class WCJ_EU_VAT_Number extends WCJ_Module {
44
  add_filter( 'woocommerce_checkout_fields', array( $this, 'add_eu_vat_number_checkout_field_to_frontend' ), PHP_INT_MAX );
45
  add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_billing_eu_vat_number_field_to_admin_order_display' ), PHP_INT_MAX );
46
  add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
 
 
47
  // add_filter( 'woocommerce_form_field_text', array( $this, 'add_eu_vat_verify_button' ), PHP_INT_MAX, 4 );
48
- add_action( 'init', array( $this, 'wcj_validate_eu_vat_number' ) );
49
- add_filter( 'woocommerce_find_rates', array( $this, 'maybe_exclude_vat' ), PHP_INT_MAX, 2 );
 
50
  add_action( 'woocommerce_after_checkout_validation', array( $this, 'checkout_validate_vat' ), PHP_INT_MAX );
51
  add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_eu_vat_number_customer_meta_field' ) );
52
  add_filter( 'default_checkout_billing_eu_vat_number', array( $this, 'add_default_checkout_billing_eu_vat_number' ), PHP_INT_MAX, 2 );
@@ -191,21 +194,28 @@ class WCJ_EU_VAT_Number extends WCJ_Module {
191
 
192
  /**
193
  * enqueue_scripts.
 
 
194
  */
195
  function enqueue_scripts() {
196
  if ( 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) {
197
  wp_enqueue_script( 'wcj-eu-vat-number', wcj_plugin_url() . '/includes/js/eu-vat-number.js', array(), false, true );
 
 
 
198
  }
199
  }
200
 
201
  /**
202
  * wcj_validate_eu_vat_number.
 
 
203
  */
204
- function wcj_validate_eu_vat_number() {
205
- if ( ! isset( $_GET['wcj_validate_eu_vat_number'] ) ) return;
206
- if ( isset( $_GET['wcj_eu_vat_number_to_check'] ) && '' != $_GET['wcj_eu_vat_number_to_check'] ) {
207
- $eu_vat_number_to_check = substr( $_GET['wcj_eu_vat_number_to_check'], 2 );
208
- $eu_vat_number_country_to_check = substr( $_GET['wcj_eu_vat_number_to_check'], 0, 2 );
209
  if ( 'yes' === apply_filters( 'wcj_get_option_filter', 'no', get_option( 'wcj_eu_vat_number_check_ip_location_country', 'no' ) ) ) {
210
  $location = WC_Geolocation::geolocate_ip();
211
  if ( empty( $location['country'] ) ) {
@@ -221,7 +231,7 @@ class WCJ_EU_VAT_Number extends WCJ_Module {
221
  $is_valid = null;
222
  }
223
  $_SESSION['wcj_is_eu_vat_number_valid'] = $is_valid;
224
- $_SESSION['wcj_eu_vat_number_to_check'] = $_GET['wcj_eu_vat_number_to_check'];
225
  echo $is_valid;
226
  die();
227
  }
@@ -229,10 +239,13 @@ class WCJ_EU_VAT_Number extends WCJ_Module {
229
  /**
230
  * maybe_exclude_vat.
231
  *
232
- * @version 2.5.2
233
  */
234
- function maybe_exclude_vat( $matched_tax_rates, $args ) {
 
235
  if (
 
 
236
  'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) &&
237
  'yes' === get_option( 'wcj_eu_vat_number_disable_for_valid', 'yes' ) &&
238
  isset( $_SESSION['wcj_is_eu_vat_number_valid'] ) && true === $_SESSION['wcj_is_eu_vat_number_valid'] && isset( $_SESSION['wcj_eu_vat_number_to_check'] )
@@ -247,15 +260,22 @@ class WCJ_EU_VAT_Number extends WCJ_Module {
247
  $preserve_base_country_check_passed = ( $location['country'] !== $selected_country ) ? true : false;
248
  }
249
  if ( $preserve_base_country_check_passed ) {
250
- $modified_matched_tax_rates = array();
251
  foreach ( $matched_tax_rates as $i => $matched_tax_rate ) {
252
  $matched_tax_rate['rate'] = 0;
253
  $modified_matched_tax_rates[ $i ] = $matched_tax_rate;
254
  }
255
- return $modified_matched_tax_rates;
 
 
 
 
 
 
 
256
  }
257
  }
258
- return $matched_tax_rates;
259
  }
260
 
261
  /**
4
  *
5
  * The WooCommerce Jetpack EU VAT Number class.
6
  *
7
+ * @version 2.5.4
8
  * @since 2.3.9
9
  * @author Algoritmika Ltd.
10
  */
18
  /**
19
  * Constructor.
20
  *
21
+ * @version 2.5.4
22
  */
23
  function __construct() {
24
 
44
  add_filter( 'woocommerce_checkout_fields', array( $this, 'add_eu_vat_number_checkout_field_to_frontend' ), PHP_INT_MAX );
45
  add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_billing_eu_vat_number_field_to_admin_order_display' ), PHP_INT_MAX );
46
  add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
47
+ add_action( 'wp_ajax_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
48
+ add_action( 'wp_ajax_nopriv_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
49
  // add_filter( 'woocommerce_form_field_text', array( $this, 'add_eu_vat_verify_button' ), PHP_INT_MAX, 4 );
50
+ // add_action( 'init', array( $this, 'wcj_validate_eu_vat_number' ) );
51
+ // add_filter( 'woocommerce_find_rates', array( $this, 'maybe_exclude_vat' ), PHP_INT_MAX, 2 );
52
+ add_filter( 'init', array( $this, 'maybe_exclude_vat' ), PHP_INT_MAX );
53
  add_action( 'woocommerce_after_checkout_validation', array( $this, 'checkout_validate_vat' ), PHP_INT_MAX );
54
  add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_eu_vat_number_customer_meta_field' ) );
55
  add_filter( 'default_checkout_billing_eu_vat_number', array( $this, 'add_default_checkout_billing_eu_vat_number' ), PHP_INT_MAX, 2 );
194
 
195
  /**
196
  * enqueue_scripts.
197
+ *
198
+ * @version 2.5.4
199
  */
200
  function enqueue_scripts() {
201
  if ( 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) {
202
  wp_enqueue_script( 'wcj-eu-vat-number', wcj_plugin_url() . '/includes/js/eu-vat-number.js', array(), false, true );
203
+ wp_localize_script( 'wcj-eu-vat-number', 'ajax_object', array(
204
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
205
+ ) );
206
  }
207
  }
208
 
209
  /**
210
  * wcj_validate_eu_vat_number.
211
+ *
212
+ * @version 2.5.4
213
  */
214
+ function wcj_validate_eu_vat_number( $param ) {
215
+ // if ( ! isset( $_GET['wcj_validate_eu_vat_number'] ) ) return;
216
+ if ( isset( $_POST['wcj_eu_vat_number_to_check'] ) && '' != $_POST['wcj_eu_vat_number_to_check'] ) {
217
+ $eu_vat_number_to_check = substr( $_POST['wcj_eu_vat_number_to_check'], 2 );
218
+ $eu_vat_number_country_to_check = substr( $_POST['wcj_eu_vat_number_to_check'], 0, 2 );
219
  if ( 'yes' === apply_filters( 'wcj_get_option_filter', 'no', get_option( 'wcj_eu_vat_number_check_ip_location_country', 'no' ) ) ) {
220
  $location = WC_Geolocation::geolocate_ip();
221
  if ( empty( $location['country'] ) ) {
231
  $is_valid = null;
232
  }
233
  $_SESSION['wcj_is_eu_vat_number_valid'] = $is_valid;
234
+ $_SESSION['wcj_eu_vat_number_to_check'] = $_POST['wcj_eu_vat_number_to_check'];
235
  echo $is_valid;
236
  die();
237
  }
239
  /**
240
  * maybe_exclude_vat.
241
  *
242
+ * @version 2.5.4
243
  */
244
+ // function maybe_exclude_vat( $matched_tax_rates, $args ) {
245
+ function maybe_exclude_vat() {
246
  if (
247
+ ( is_checkout() || is_cart() || defined( 'WOOCOMMERCE_CHECKOUT' ) || defined( 'WOOCOMMERCE_CART' ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) &&
248
+ ! empty( WC()->customer ) &&
249
  'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) &&
250
  'yes' === get_option( 'wcj_eu_vat_number_disable_for_valid', 'yes' ) &&
251
  isset( $_SESSION['wcj_is_eu_vat_number_valid'] ) && true === $_SESSION['wcj_is_eu_vat_number_valid'] && isset( $_SESSION['wcj_eu_vat_number_to_check'] )
260
  $preserve_base_country_check_passed = ( $location['country'] !== $selected_country ) ? true : false;
261
  }
262
  if ( $preserve_base_country_check_passed ) {
263
+ /* $modified_matched_tax_rates = array();
264
  foreach ( $matched_tax_rates as $i => $matched_tax_rate ) {
265
  $matched_tax_rate['rate'] = 0;
266
  $modified_matched_tax_rates[ $i ] = $matched_tax_rate;
267
  }
268
+ return $modified_matched_tax_rates; */
269
+ WC()->customer->set_is_vat_exempt( true );
270
+ } else {
271
+ WC()->customer->set_is_vat_exempt( false );
272
+ }
273
+ } else {
274
+ if ( ! empty( WC()->customer ) ) {
275
+ WC()->customer->set_is_vat_exempt( false );
276
  }
277
  }
278
+ // return $matched_tax_rates;
279
  }
280
 
281
  /**
includes/class-wcj-export-import.php ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WooCommerce Jetpack Export Import
4
+ *
5
+ * The WooCommerce Jetpack Export Import class.
6
+ *
7
+ * @version 2.5.4
8
+ * @since 2.5.4
9
+ * @author Algoritmika Ltd.
10
+ * @todo import products (maybe orders, customers) tool(s);
11
+ */
12
+
13
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
14
+
15
+ if ( ! class_exists( 'WCJ_Export_Import' ) ) :
16
+
17
+ class WCJ_Export_Import extends WCJ_Module {
18
+
19
+ /**
20
+ * Constructor.
21
+ *
22
+ * @version 2.5.4
23
+ * @since 2.5.4
24
+ */
25
+ public function __construct() {
26
+
27
+ $this->id = 'export';
28
+ $this->short_desc = __( 'Export', 'woocommerce-jetpack' );
29
+ $this->desc = __( 'WooCommerce export tools.', 'woocommerce-jetpack' );
30
+ $this->link = 'http://booster.io/features/woocommerce-export-tools/';
31
+ parent::__construct();
32
+
33
+ $this->add_tools( array(
34
+ 'export_customers' => array(
35
+ 'title' => __( 'Export Customers', 'woocommerce-jetpack' ),
36
+ 'desc' => __( 'Export Customers.', 'woocommerce-jetpack' ),
37
+ ),
38
+ 'export_customers_from_orders' => array(
39
+ 'title' => __( 'Export Customers from Orders', 'woocommerce-jetpack' ),
40
+ 'desc' => __( 'Export Customers (extracted from orders).', 'woocommerce-jetpack' ),
41
+ ),
42
+ 'export_orders' => array(
43
+ 'title' => __( 'Export Orders', 'woocommerce-jetpack' ),
44
+ 'desc' => __( 'Export Orders.', 'woocommerce-jetpack' ),
45
+ ),
46
+ 'export_products' => array(
47
+ 'title' => __( 'Export Products', 'woocommerce-jetpack' ),
48
+ 'desc' => __( 'Export Products.', 'woocommerce-jetpack' ),
49
+ ),
50
+ ) );
51
+
52
+ if ( $this->is_enabled() ) {
53
+ add_action( 'init', array( $this, 'export_csv' ) );
54
+ }
55
+ }
56
+
57
+ /**
58
+ * export.
59
+ *
60
+ * @version 2.5.3
61
+ * @since 2.4.8
62
+ */
63
+ function export( $tool_id ) {
64
+ $data = array();
65
+ switch ( $tool_id ) {
66
+ case 'customers':
67
+ $data = $this->export_customers();
68
+ break;
69
+ case 'customers_from_orders':
70
+ $data = $this->export_customers_from_orders();
71
+ break;
72
+ case 'orders':
73
+ $data = $this->export_orders();
74
+ break;
75
+ case 'products':
76
+ $data = $this->export_products();
77
+ break;
78
+ }
79
+ return $data;
80
+ }
81
+
82
+ /**
83
+ * export_csv.
84
+ *
85
+ * @version 2.4.8
86
+ * @since 2.4.8
87
+ */
88
+ function export_csv() {
89
+ if ( isset( $_POST['wcj_export'] ) ) {
90
+ $data = $this->export( $_POST['wcj_export'] );
91
+ $csv = '';
92
+ foreach ( $data as $row ) {
93
+ $csv .= implode( ',', $row ) . PHP_EOL;
94
+ }
95
+ header( "Content-Type: application/octet-stream" );
96
+ header( "Content-Disposition: attachment; filename=" . $_POST['wcj_export'] . ".csv" );
97
+ header( "Content-Type: application/octet-stream" );
98
+ header( "Content-Type: application/download" );
99
+ header( "Content-Description: File Transfer" );
100
+ header( "Content-Length: " . strlen( $csv ) );
101
+ echo $csv;
102
+ }
103
+ }
104
+
105
+ /**
106
+ * create_export_tool.
107
+ *
108
+ * @version 2.4.8
109
+ * @since 2.4.8
110
+ */
111
+ function create_export_tool( $tool_id ) {
112
+ $data = $this->export( $tool_id );
113
+ echo '<p><form method="post" action="">';
114
+ echo '<button class="button-primary" type="submit" name="wcj_export" value="' . $tool_id . '">' . __( 'Download CSV', 'woocommerce-jetpack' ) . '</button>';
115
+ echo '</form></p>';
116
+ echo wcj_get_table_html( $data, array( 'table_class' => 'widefat striped' ) );
117
+ }
118
+
119
+ /**
120
+ * create_export_customers_tool.
121
+ *
122
+ * @version 2.4.8
123
+ * @since 2.4.8
124
+ */
125
+ function create_export_customers_tool() {
126
+ $this->create_export_tool( 'customers' );
127
+ }
128
+
129
+ /**
130
+ * create_export_orders_tool.
131
+ *
132
+ * @version 2.4.8
133
+ * @since 2.4.8
134
+ */
135
+ function create_export_orders_tool() {
136
+ $this->create_export_tool( 'orders' );
137
+ }
138
+
139
+ /**
140
+ * create_export_products_tool.
141
+ *
142
+ * @version 2.5.3
143
+ * @since 2.5.3
144
+ */
145
+ function create_export_products_tool() {
146
+ $this->create_export_tool( 'products' );
147
+ }
148
+
149
+ /**
150
+ * create_export_customers_from_orders_tool.
151
+ *
152
+ * @version 2.4.8
153
+ * @since 2.3.9
154
+ */
155
+ function create_export_customers_from_orders_tool() {
156
+ $this->create_export_tool( 'customers_from_orders' );
157
+ }
158
+
159
+ /**
160
+ * export_customers.
161
+ *
162
+ * @version 2.4.8
163
+ * @since 2.4.8
164
+ */
165
+ function export_customers() {
166
+ $data = array();
167
+ $data[] = array(
168
+ __( 'Customer ID', 'woocommerce-jetpack' ),
169
+ __( 'Customer Email', 'woocommerce-jetpack' ),
170
+ __( 'Customer First Name', 'woocommerce-jetpack' ),
171
+ __( 'Customer Last Name', 'woocommerce-jetpack' ),
172
+ );
173
+ $customers = get_users( 'role=customer' );
174
+ foreach ( $customers as $customer ) {
175
+ $data[] = array( $customer->ID, $customer->user_email, $customer->first_name, $customer->last_name, );
176
+ }
177
+ return $data;
178
+ }
179
+
180
+ /**
181
+ * export_orders.
182
+ *
183
+ * @version 2.5.4
184
+ * @since 2.4.8
185
+ */
186
+ function export_orders() {
187
+ $data = array();
188
+ $data[] = array(
189
+ __( 'Order ID', 'woocommerce-jetpack' ),
190
+ __( 'Order Number', 'woocommerce-jetpack' ),
191
+ __( 'Order Status', 'woocommerce-jetpack' ),
192
+ __( 'Order Date', 'woocommerce-jetpack' ),
193
+ __( 'Order Item Count', 'woocommerce-jetpack' ),
194
+ __( 'Order Total', 'woocommerce-jetpack' ),
195
+ __( 'Order Payment Method', 'woocommerce-jetpack' ),
196
+ __( 'Billing First Name', 'woocommerce-jetpack' ),
197
+ __( 'Billing Last Name', 'woocommerce-jetpack' ),
198
+ __( 'Billing Company', 'woocommerce-jetpack' ),
199
+ __( 'Billing Address 1', 'woocommerce-jetpack' ),
200
+ __( 'Billing Address 2', 'woocommerce-jetpack' ),
201
+ __( 'Billing City', 'woocommerce-jetpack' ),
202
+ __( 'Billing State', 'woocommerce-jetpack' ),
203
+ __( 'Billing Postcode', 'woocommerce-jetpack' ),
204
+ __( 'Billing Country', 'woocommerce-jetpack' ),
205
+ __( 'Billing Phone', 'woocommerce-jetpack' ),
206
+ __( 'Billing Email', 'woocommerce-jetpack' ),
207
+ __( 'Shipping First Name', 'woocommerce-jetpack' ),
208
+ __( 'Shipping Last Name', 'woocommerce-jetpack' ),
209
+ __( 'Shipping Company', 'woocommerce-jetpack' ),
210
+ __( 'Shipping Address 1', 'woocommerce-jetpack' ),
211
+ __( 'Shipping Address 2', 'woocommerce-jetpack' ),
212
+ __( 'Shipping City', 'woocommerce-jetpack' ),
213
+ __( 'Shipping State', 'woocommerce-jetpack' ),
214
+ __( 'Shipping Postcode', 'woocommerce-jetpack' ),
215
+ __( 'Shipping Country', 'woocommerce-jetpack' ),
216
+ );
217
+ $offset = 0;
218
+ $block_size = 96;
219
+ while( true ) {
220
+ $args_orders = array(
221
+ 'post_type' => 'shop_order',
222
+ 'post_status' => 'any',
223
+ 'posts_per_page' => $block_size,
224
+ 'orderby' => 'date',
225
+ 'order' => 'DESC',
226
+ 'offset' => $offset,
227
+ );
228
+ $loop_orders = new WP_Query( $args_orders );
229
+ if ( ! $loop_orders->have_posts() ) break;
230
+ while ( $loop_orders->have_posts() ) : $loop_orders->the_post();
231
+ $order_id = $loop_orders->post->ID;
232
+ $order = wc_get_order( $order_id );
233
+ $data[] = array(
234
+ $order_id,
235
+ $order->get_order_number(),
236
+ $order->get_status(),
237
+ get_the_date( 'Y/m/d' ),
238
+ $order->get_item_count(),
239
+ $order->get_total() . ' ' . $order->get_order_currency(),
240
+ $order->payment_method_title,
241
+ $order->billing_first_name,
242
+ $order->billing_last_name,
243
+ $order->billing_company,
244
+ $order->billing_address_1,
245
+ $order->billing_address_2,
246
+ $order->billing_city,
247
+ $order->billing_state,
248
+ $order->billing_postcode,
249
+ $order->billing_country,
250
+ $order->billing_phone,
251
+ $order->billing_email,
252
+ $order->shipping_first_name,
253
+ $order->shipping_last_name,
254
+ $order->shipping_company,
255
+ $order->shipping_address_1,
256
+ $order->shipping_address_2,
257
+ $order->shipping_city,
258
+ $order->shipping_state,
259
+ $order->shipping_postcode,
260
+ $order->shipping_country,
261
+ );
262
+ endwhile;
263
+ $offset += $block_size;
264
+ }
265
+ return $data;
266
+ }
267
+
268
+ /**
269
+ * export_products.
270
+ *
271
+ * @version 2.5.3
272
+ * @since 2.5.3
273
+ */
274
+ function export_products() {
275
+ $data = array();
276
+ $data[] = array(
277
+ __( 'Product ID', 'woocommerce-jetpack' ),
278
+ __( 'Name', 'woocommerce-jetpack' ),
279
+ __( 'SKU', 'woocommerce-jetpack' ),
280
+ __( 'Stock', 'woocommerce-jetpack' ),
281
+ __( 'Regular Price', 'woocommerce-jetpack' ),
282
+ __( 'Sale Price', 'woocommerce-jetpack' ),
283
+ __( 'Price', 'woocommerce-jetpack' ),
284
+ __( 'Type', 'woocommerce-jetpack' ),
285
+ // __( 'Attributes', 'woocommerce-jetpack' ),
286
+ );
287
+ $offset = 0;
288
+ $block_size = 96;
289
+ while( true ) {
290
+ $args = array(
291
+ 'post_type' => 'product',
292
+ 'post_status' => 'any',
293
+ 'posts_per_page' => $block_size,
294
+ 'orderby' => 'date',
295
+ 'order' => 'DESC',
296
+ 'offset' => $offset,
297
+ );
298
+ $loop = new WP_Query( $args );
299
+ if ( ! $loop->have_posts() ) break;
300
+ while ( $loop->have_posts() ) : $loop->the_post();
301
+ $product_id = $loop->post->ID;
302
+ $_product = wc_get_product( $product_id );
303
+ $data[] = array(
304
+ $product_id,
305
+ $_product->get_title(),
306
+ $_product->get_sku(),
307
+ $_product->/* get_total_stock() */get_stock_quantity(),
308
+ $_product->get_regular_price(),
309
+ $_product->get_sale_price(),
310
+ ( $_product->is_type( 'variable' ) || $_product->is_type( 'grouped' ) ? '' : $_product->get_price() ),
311
+ $_product->get_type(),
312
+ // ( ! empty( $_product->get_attributes() ) ? serialize( $_product->get_attributes() ) : '' ),
313
+ );
314
+ endwhile;
315
+ $offset += $block_size;
316
+ }
317
+ return $data;
318
+ }
319
+
320
+ /**
321
+ * export_customers_from_orders.
322
+ *
323
+ * @version 2.4.8
324
+ * @since 2.4.8
325
+ */
326
+ function export_customers_from_orders() {
327
+ $data = array();
328
+ $data[] = array(
329
+ __( 'Nr.', 'woocommerce-jetpack' ),
330
+ __( 'Email', 'woocommerce-jetpack' ),
331
+ __( 'First Name', 'woocommerce-jetpack' ),
332
+ __( 'Last Name', 'woocommerce-jetpack' ),
333
+ __( 'Last Order Date', 'woocommerce-jetpack' ),
334
+ );
335
+ $total_customers = 0;
336
+ $orders = array();
337
+ $offset = 0;
338
+ $block_size = 96;
339
+ while( true ) {
340
+ $args_orders = array(
341
+ 'post_type' => 'shop_order',
342
+ 'post_status' => 'any',
343
+ 'posts_per_page' => $block_size,
344
+ 'orderby' => 'date',
345
+ 'order' => 'DESC',
346
+ 'offset' => $offset,
347
+ );
348
+ $loop_orders = new WP_Query( $args_orders );
349
+ if ( ! $loop_orders->have_posts() ) break;
350
+ while ( $loop_orders->have_posts() ) : $loop_orders->the_post();
351
+ $order_id = $loop_orders->post->ID;
352
+ $order = wc_get_order( $order_id );
353
+ if ( isset( $order->billing_email ) && '' != $order->billing_email && ! in_array( $order->billing_email, $orders ) ) {
354
+ $emails_to_skip = array();
355
+ if ( ! in_array( $order->billing_email, $emails_to_skip ) ) {
356
+ $total_customers++;
357
+ $data[] = array( $total_customers, $order->billing_email, $order->billing_first_name, $order->billing_last_name, get_the_date( 'Y/m/d' ), );
358
+ $orders[] = $order->billing_email;
359
+ }
360
+ }
361
+ endwhile;
362
+ $offset += $block_size;
363
+ }
364
+ return $data;
365
+ }
366
+
367
+ /**
368
+ * get_settings.
369
+ *
370
+ * @version 2.5.4
371
+ * @since 2.5.4
372
+ */
373
+ function get_settings() {
374
+ $settings = array();
375
+ return $this->add_standard_settings( $settings );
376
+ }
377
+ }
378
+
379
+ endif;
380
+
381
+ return new WCJ_Export_Import();
includes/class-wcj-general.php CHANGED
@@ -4,9 +4,8 @@
4
  *
5
  * The WooCommerce Jetpack General class.
6
  *
7
- * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
- * @todo import products tool;
10
  */
11
 
12
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
@@ -18,13 +17,13 @@ class WCJ_General extends WCJ_Module {
18
  /**
19
  * Constructor.
20
  *
21
- * @version 2.5.3
22
  */
23
  public function __construct() {
24
 
25
  $this->id = 'general';
26
  $this->short_desc = __( 'General', 'woocommerce-jetpack' );
27
- $this->desc = __( 'Separate custom CSS for front and back end. Shortcodes in Wordpress text widgets. Export tools. Custom roles tool.', 'woocommerce-jetpack' );
28
  $this->link = 'http://booster.io/features/woocommerce-booster-general-tools/';
29
  parent::__construct();
30
 
@@ -33,22 +32,6 @@ class WCJ_General extends WCJ_Module {
33
  'title' => __( 'Products Atts', 'woocommerce-jetpack' ),
34
  'desc' => __( 'All Products and All Attributes.', 'woocommerce-jetpack' ),
35
  ),
36
- 'export_customers' => array(
37
- 'title' => __( 'Export Customers', 'woocommerce-jetpack' ),
38
- 'desc' => __( 'Export Customers.', 'woocommerce-jetpack' ),
39
- ),
40
- 'export_customers_from_orders' => array(
41
- 'title' => __( 'Export Customers from Orders', 'woocommerce-jetpack' ),
42
- 'desc' => __( 'Export Customers (extracted from orders).', 'woocommerce-jetpack' ),
43
- ),
44
- 'export_orders' => array(
45
- 'title' => __( 'Export Orders', 'woocommerce-jetpack' ),
46
- 'desc' => __( 'Export Orders.', 'woocommerce-jetpack' ),
47
- ),
48
- 'export_products' => array(
49
- 'title' => __( 'Export Products', 'woocommerce-jetpack' ),
50
- 'desc' => __( 'Export Products.', 'woocommerce-jetpack' ),
51
- ),
52
  'custom_roles' => array(
53
  'title' => __( 'Add/Manage Custom Roles', 'woocommerce-jetpack' ),
54
  'tab_title' => __( 'Custom Roles', 'woocommerce-jetpack' ),
@@ -73,8 +56,6 @@ class WCJ_General extends WCJ_Module {
73
  add_action( 'admin_head', array( $this, 'hook_custom_admin_css' ) );
74
  }
75
 
76
- add_action( 'init', array( $this, 'export_csv' ) );
77
-
78
  if ( 'yes' === get_option( 'wcj_paypal_email_per_product_enabled', 'no' ) ) {
79
 
80
  add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
@@ -195,266 +176,6 @@ class WCJ_General extends WCJ_Module {
195
  return $args;
196
  }
197
 
198
- /**
199
- * export.
200
- *
201
- * @version 2.5.3
202
- * @since 2.4.8
203
- */
204
- function export( $tool_id ) {
205
- $data = array();
206
- switch ( $tool_id ) {
207
- case 'customers':
208
- $data = $this->export_customers();
209
- break;
210
- case 'customers_from_orders':
211
- $data = $this->export_customers_from_orders();
212
- break;
213
- case 'orders':
214
- $data = $this->export_orders();
215
- break;
216
- case 'products':
217
- $data = $this->export_products();
218
- break;
219
- }
220
- return $data;
221
- }
222
-
223
- /**
224
- * export_csv.
225
- *
226
- * @version 2.4.8
227
- * @since 2.4.8
228
- */
229
- function export_csv() {
230
- if ( isset( $_POST['wcj_export'] ) ) {
231
- $data = $this->export( $_POST['wcj_export'] );
232
- $csv = '';
233
- foreach ( $data as $row ) {
234
- $csv .= implode( ',', $row ) . PHP_EOL;
235
- }
236
- header( "Content-Type: application/octet-stream" );
237
- header( "Content-Disposition: attachment; filename=" . $_POST['wcj_export'] . ".csv" );
238
- header( "Content-Type: application/octet-stream" );
239
- header( "Content-Type: application/download" );
240
- header( "Content-Description: File Transfer" );
241
- header( "Content-Length: " . strlen( $csv ) );
242
- echo $csv;
243
- }
244
- }
245
-
246
- /**
247
- * create_export_tool.
248
- *
249
- * @version 2.4.8
250
- * @since 2.4.8
251
- */
252
- function create_export_tool( $tool_id ) {
253
- $data = $this->export( $tool_id );
254
- echo '<p><form method="post" action="">';
255
- echo '<button class="button-primary" type="submit" name="wcj_export" value="' . $tool_id . '">' . __( 'Download CSV', 'woocommerce-jetpack' ) . '</button>';
256
- echo '</form></p>';
257
- echo wcj_get_table_html( $data, array( 'table_class' => 'widefat striped' ) );
258
- }
259
-
260
- /**
261
- * create_export_customers_tool.
262
- *
263
- * @version 2.4.8
264
- * @since 2.4.8
265
- */
266
- function create_export_customers_tool() {
267
- $this->create_export_tool( 'customers' );
268
- }
269
-
270
- /**
271
- * create_export_orders_tool.
272
- *
273
- * @version 2.4.8
274
- * @since 2.4.8
275
- */
276
- function create_export_orders_tool() {
277
- $this->create_export_tool( 'orders' );
278
- }
279
-
280
- /**
281
- * create_export_products_tool.
282
- *
283
- * @version 2.5.3
284
- * @since 2.5.3
285
- */
286
- function create_export_products_tool() {
287
- $this->create_export_tool( 'products' );
288
- }
289
-
290
- /**
291
- * create_export_customers_from_orders_tool.
292
- *
293
- * @version 2.4.8
294
- * @since 2.3.9
295
- */
296
- function create_export_customers_from_orders_tool() {
297
- $this->create_export_tool( 'customers_from_orders' );
298
- }
299
-
300
- /**
301
- * export_customers.
302
- *
303
- * @version 2.4.8
304
- * @since 2.4.8
305
- */
306
- function export_customers() {
307
- $data = array();
308
- $data[] = array(
309
- __( 'Customer ID', 'woocommerce-jetpack' ),
310
- __( 'Customer Email', 'woocommerce-jetpack' ),
311
- __( 'Customer First Name', 'woocommerce-jetpack' ),
312
- __( 'Customer Last Name', 'woocommerce-jetpack' ),
313
- );
314
- $customers = get_users( 'role=customer' );
315
- foreach ( $customers as $customer ) {
316
- $data[] = array( $customer->ID, $customer->user_email, $customer->first_name, $customer->last_name, );
317
- }
318
- return $data;
319
- }
320
-
321
- /**
322
- * export_orders.
323
- *
324
- * @version 2.4.8
325
- * @since 2.4.8
326
- */
327
- function export_orders() {
328
- $data = array();
329
- $data[] = array(
330
- __( 'Order ID', 'woocommerce-jetpack' ),
331
- __( 'Customer Email', 'woocommerce-jetpack' ),
332
- __( 'Customer First Name', 'woocommerce-jetpack' ),
333
- __( 'Customer Last Name', 'woocommerce-jetpack' ),
334
- __( 'Order Date', 'woocommerce-jetpack' ),
335
- );
336
- $offset = 0;
337
- $block_size = 96;
338
- while( true ) {
339
- $args_orders = array(
340
- 'post_type' => 'shop_order',
341
- 'post_status' => 'any',
342
- 'posts_per_page' => $block_size,
343
- 'orderby' => 'date',
344
- 'order' => 'DESC',
345
- 'offset' => $offset,
346
- );
347
- $loop_orders = new WP_Query( $args_orders );
348
- if ( ! $loop_orders->have_posts() ) break;
349
- while ( $loop_orders->have_posts() ) : $loop_orders->the_post();
350
- $order_id = $loop_orders->post->ID;
351
- $order = wc_get_order( $order_id );
352
- $data[] = array( $order_id, $order->billing_email, $order->billing_first_name, $order->billing_last_name, get_the_date( 'Y/m/d' ), );
353
- endwhile;
354
- $offset += $block_size;
355
- }
356
- return $data;
357
- }
358
-
359
- /**
360
- * export_products.
361
- *
362
- * @version 2.5.3
363
- * @since 2.5.3
364
- */
365
- function export_products() {
366
- $data = array();
367
- $data[] = array(
368
- __( 'Product ID', 'woocommerce-jetpack' ),
369
- __( 'Name', 'woocommerce-jetpack' ),
370
- __( 'SKU', 'woocommerce-jetpack' ),
371
- __( 'Stock', 'woocommerce-jetpack' ),
372
- __( 'Regular Price', 'woocommerce-jetpack' ),
373
- __( 'Sale Price', 'woocommerce-jetpack' ),
374
- __( 'Price', 'woocommerce-jetpack' ),
375
- __( 'Type', 'woocommerce-jetpack' ),
376
- // __( 'Attributes', 'woocommerce-jetpack' ),
377
- );
378
- $offset = 0;
379
- $block_size = 96;
380
- while( true ) {
381
- $args = array(
382
- 'post_type' => 'product',
383
- 'post_status' => 'any',
384
- 'posts_per_page' => $block_size,
385
- 'orderby' => 'date',
386
- 'order' => 'DESC',
387
- 'offset' => $offset,
388
- );
389
- $loop = new WP_Query( $args );
390
- if ( ! $loop->have_posts() ) break;
391
- while ( $loop->have_posts() ) : $loop->the_post();
392
- $product_id = $loop->post->ID;
393
- $_product = wc_get_product( $product_id );
394
- $data[] = array(
395
- $product_id,
396
- $_product->get_title(),
397
- $_product->get_sku(),
398
- $_product->/* get_total_stock() */get_stock_quantity(),
399
- $_product->get_regular_price(),
400
- $_product->get_sale_price(),
401
- ( $_product->is_type( 'variable' ) || $_product->is_type( 'grouped' ) ? '' : $_product->get_price() ),
402
- $_product->get_type(),
403
- // ( ! empty( $_product->get_attributes() ) ? serialize( $_product->get_attributes() ) : '' ),
404
- );
405
- endwhile;
406
- $offset += $block_size;
407
- }
408
- return $data;
409
- }
410
-
411
- /**
412
- * export_customers_from_orders.
413
- *
414
- * @version 2.4.8
415
- * @since 2.4.8
416
- */
417
- function export_customers_from_orders() {
418
- $data = array();
419
- $data[] = array(
420
- __( 'Nr.', 'woocommerce-jetpack' ),
421
- __( 'Email', 'woocommerce-jetpack' ),
422
- __( 'First Name', 'woocommerce-jetpack' ),
423
- __( 'Last Name', 'woocommerce-jetpack' ),
424
- __( 'Last Order Date', 'woocommerce-jetpack' ),
425
- );
426
- $total_customers = 0;
427
- $orders = array();
428
- $offset = 0;
429
- $block_size = 96;
430
- while( true ) {
431
- $args_orders = array(
432
- 'post_type' => 'shop_order',
433
- 'post_status' => 'any',
434
- 'posts_per_page' => $block_size,
435
- 'orderby' => 'date',
436
- 'order' => 'DESC',
437
- 'offset' => $offset,
438
- );
439
- $loop_orders = new WP_Query( $args_orders );
440
- if ( ! $loop_orders->have_posts() ) break;
441
- while ( $loop_orders->have_posts() ) : $loop_orders->the_post();
442
- $order_id = $loop_orders->post->ID;
443
- $order = wc_get_order( $order_id );
444
- if ( isset( $order->billing_email ) && '' != $order->billing_email && ! in_array( $order->billing_email, $orders ) ) {
445
- $emails_to_skip = array();
446
- if ( ! in_array( $order->billing_email, $emails_to_skip ) ) {
447
- $total_customers++;
448
- $data[] = array( $total_customers, $order->billing_email, $order->billing_first_name, $order->billing_last_name, get_the_date( 'Y/m/d' ), );
449
- $orders[] = $order->billing_email;
450
- }
451
- }
452
- endwhile;
453
- $offset += $block_size;
454
- }
455
- return $data;
456
- }
457
-
458
  /**
459
  * create_products_atts_tool.
460
  *
4
  *
5
  * The WooCommerce Jetpack General class.
6
  *
7
+ * @version 2.5.4
8
  * @author Algoritmika Ltd.
 
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
17
  /**
18
  * Constructor.
19
  *
20
+ * @version 2.5.4
21
  */
22
  public function __construct() {
23
 
24
  $this->id = 'general';
25
  $this->short_desc = __( 'General', 'woocommerce-jetpack' );
26
+ $this->desc = __( 'Separate custom CSS for front and back end. Shortcodes in Wordpress text widgets. Custom roles tool.', 'woocommerce-jetpack' );
27
  $this->link = 'http://booster.io/features/woocommerce-booster-general-tools/';
28
  parent::__construct();
29
 
32
  'title' => __( 'Products Atts', 'woocommerce-jetpack' ),
33
  'desc' => __( 'All Products and All Attributes.', 'woocommerce-jetpack' ),
34
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  'custom_roles' => array(
36
  'title' => __( 'Add/Manage Custom Roles', 'woocommerce-jetpack' ),
37
  'tab_title' => __( 'Custom Roles', 'woocommerce-jetpack' ),
56
  add_action( 'admin_head', array( $this, 'hook_custom_admin_css' ) );
57
  }
58
 
 
 
59
  if ( 'yes' === get_option( 'wcj_paypal_email_per_product_enabled', 'no' ) ) {
60
 
61
  add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
176
  return $args;
177
  }
178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  /**
180
  * create_products_atts_tool.
181
  *
includes/class-wcj-price-by-country.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Price by Country class.
6
  *
7
- * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -111,7 +111,7 @@ class WCJ_Price_By_Country extends WCJ_Module {
111
  /**
112
  * get_settings.
113
  *
114
- * @version 2.5.3
115
  */
116
  function get_settings() {
117
 
@@ -198,6 +198,15 @@ class WCJ_Price_By_Country extends WCJ_Module {
198
  'type' => 'checkbox',
199
  ),
200
 
 
 
 
 
 
 
 
 
 
201
  array( 'type' => 'sectionend', 'id' => 'wcj_price_by_country_options' ),
202
 
203
  array(
4
  *
5
  * The WooCommerce Jetpack Price by Country class.
6
  *
7
+ * @version 2.5.4
8
  * @author Algoritmika Ltd.
9
  */
10
 
111
  /**
112
  * get_settings.
113
  *
114
+ * @version 2.5.4
115
  */
116
  function get_settings() {
117
 
198
  'type' => 'checkbox',
199
  ),
200
 
201
+ array(
202
+ 'title' => __( 'Add Countries Flags Images to Select Drop-Down Box', 'woocommerce-jetpack' ),
203
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
204
+ 'desc_tip' => __( 'If you are using [wcj_country_select_drop_down_list] shortcode or "Booster: Country Switcher" widget, this will add country flags to these select boxes.', 'woocommerce-jetpack' ),
205
+ 'id' => 'wcj_price_by_country_jquery_wselect_enabled',
206
+ 'default' => 'no',
207
+ 'type' => 'checkbox',
208
+ ),
209
+
210
  array( 'type' => 'sectionend', 'id' => 'wcj_price_by_country_options' ),
211
 
212
  array(
includes/class-wcj-product-by-user.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Product by User class.
6
  *
7
- * @version 2.5.3
8
  * @since 2.5.2
9
  * @author Algoritmika Ltd.
10
  */
@@ -44,7 +44,7 @@ class WCJ_Product_By_User extends WCJ_Module {
44
  *
45
  * @version 2.5.2
46
  * @since 2.5.2
47
- * @todo check if user's products exist
48
  */
49
  function add_my_products_tab_my_account_page( $items ) {
50
  $items['wcj-my-products'] = __( 'My Products', 'woocommerce-jetpack' );
@@ -118,7 +118,7 @@ class WCJ_Product_By_User extends WCJ_Module {
118
  /* $i . ' [' . $_product_id . ']' . */ get_the_post_thumbnail( $_product_id, array( 25, 25 ) ),
119
  '<code>'. $_product_data['status'] . '</code>',
120
  $_product_data['title'],
121
- '<a class="button" href="' . add_query_arg( 'wcj_edit_product', $_product_id, remove_query_arg( array( 'wcj_edit_product_image_delete', 'wcj_delete_product' ) ) ) . '">' . __( 'Edit', 'woocommerce-jetpack' ) . '</a>' . ' ' .
122
  '<a class="button" href="' . add_query_arg( 'wcj_delete_product', $_product_id, remove_query_arg( array( 'wcj_edit_product_image_delete', 'wcj_edit_product' ) ) ) . '" onclick="return confirm(\'' . __( 'Are you sure?', 'woocommerce-jetpack' ) . '\')">' . __( 'Delete', 'woocommerce-jetpack' ) . '</a>',
123
  );
124
  }
@@ -150,7 +150,7 @@ class WCJ_Product_By_User extends WCJ_Module {
150
  /**
151
  * add_settings.
152
  *
153
- * @version 2.5.3
154
  * @since 2.5.3
155
  */
156
  function add_settings() {
@@ -227,6 +227,13 @@ class WCJ_Product_By_User extends WCJ_Module {
227
  'type' => 'select',
228
  'options' => get_post_statuses(),
229
  ),
 
 
 
 
 
 
 
230
  array(
231
  'title' => __( 'Add "My Products" Tab to User\'s My Account Page', 'woocommerce-jetpack' ),
232
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
@@ -234,6 +241,20 @@ class WCJ_Product_By_User extends WCJ_Module {
234
  'default' => 'yes',
235
  'type' => 'checkbox',
236
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  array(
238
  'type' => 'sectionend',
239
  'id' => 'wcj_product_by_user_options',
4
  *
5
  * The WooCommerce Jetpack Product by User class.
6
  *
7
+ * @version 2.5.4
8
  * @since 2.5.2
9
  * @author Algoritmika Ltd.
10
  */
44
  *
45
  * @version 2.5.2
46
  * @since 2.5.2
47
+ * @todo check if any user's products exist
48
  */
49
  function add_my_products_tab_my_account_page( $items ) {
50
  $items['wcj-my-products'] = __( 'My Products', 'woocommerce-jetpack' );
118
  /* $i . ' [' . $_product_id . ']' . */ get_the_post_thumbnail( $_product_id, array( 25, 25 ) ),
119
  '<code>'. $_product_data['status'] . '</code>',
120
  $_product_data['title'],
121
+ '<a class="button" href="' . add_query_arg( 'wcj_edit_product', $_product_id, remove_query_arg( array( 'wcj_edit_product_image_delete', 'wcj_delete_product' ) ) ) . '">' . __( 'Edit', 'woocommerce-jetpack' ) . '</a>' . ' ' .
122
  '<a class="button" href="' . add_query_arg( 'wcj_delete_product', $_product_id, remove_query_arg( array( 'wcj_edit_product_image_delete', 'wcj_edit_product' ) ) ) . '" onclick="return confirm(\'' . __( 'Are you sure?', 'woocommerce-jetpack' ) . '\')">' . __( 'Delete', 'woocommerce-jetpack' ) . '</a>',
123
  );
124
  }
150
  /**
151
  * add_settings.
152
  *
153
+ * @version 2.5.4
154
  * @since 2.5.3
155
  */
156
  function add_settings() {
227
  'type' => 'select',
228
  'options' => get_post_statuses(),
229
  ),
230
+ array(
231
+ 'title' => __( 'Require Unique Title', 'woocommerce-jetpack' ),
232
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
233
+ 'id' => 'wcj_product_by_user_require_unique_title',
234
+ 'default' => 'no',
235
+ 'type' => 'checkbox',
236
+ ),
237
  array(
238
  'title' => __( 'Add "My Products" Tab to User\'s My Account Page', 'woocommerce-jetpack' ),
239
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
241
  'default' => 'yes',
242
  'type' => 'checkbox',
243
  ),
244
+ array(
245
+ 'title' => __( 'Message: Product Successfully Added', 'woocommerce-jetpack' ),
246
+ 'id' => 'wcj_product_by_user_message_product_successfully_added',
247
+ 'default' => __( '"%product_title%" successfully added!', 'woocommerce-jetpack' ),
248
+ 'type' => 'text',
249
+ 'css' => 'width:300px;',
250
+ ),
251
+ array(
252
+ 'title' => __( 'Message: Product Successfully Edited', 'woocommerce-jetpack' ),
253
+ 'id' => 'wcj_product_by_user_message_product_successfully_edited',
254
+ 'default' => __( '"%product_title%" successfully edited!', 'woocommerce-jetpack' ),
255
+ 'type' => 'text',
256
+ 'css' => 'width:300px;',
257
+ ),
258
  array(
259
  'type' => 'sectionend',
260
  'id' => 'wcj_product_by_user_options',
includes/class-wcj-wholesale-price.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Wholesale Price class.
6
  *
7
- * @version 2.5.2
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  * @todo per variation;
@@ -273,7 +273,7 @@ class WCJ_Wholesale_Price extends WCJ_Module {
273
  /**
274
  * get_settings.
275
  *
276
- * @version 2.5.0
277
  */
278
  function get_settings() {
279
  $products = apply_filters( 'wcj_get_products_filter', array() );
@@ -338,6 +338,14 @@ class WCJ_Wholesale_Price extends WCJ_Module {
338
  'class' => 'chosen_select',
339
  'options' => $products,
340
  ),
 
 
 
 
 
 
 
 
341
  array(
342
  'title' => __( 'Number of levels', 'woocommerce-jetpack' ),
343
  'id' => 'wcj_wholesale_price_levels_number',
4
  *
5
  * The WooCommerce Jetpack Wholesale Price class.
6
  *
7
+ * @version 2.5.4
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  * @todo per variation;
273
  /**
274
  * get_settings.
275
  *
276
+ * @version 2.5.4
277
  */
278
  function get_settings() {
279
  $products = apply_filters( 'wcj_get_products_filter', array() );
338
  'class' => 'chosen_select',
339
  'options' => $products,
340
  ),
341
+ array(
342
+ 'title' => __( 'Products to exclude', 'woocommerce-jetpack' ),
343
+ 'id' => 'wcj_wholesale_price_products_to_exclude',
344
+ 'default' => '',
345
+ 'type' => 'multiselect',
346
+ 'class' => 'chosen_select',
347
+ 'options' => $products,
348
+ ),
349
  array(
350
  'title' => __( 'Number of levels', 'woocommerce-jetpack' ),
351
  'id' => 'wcj_wholesale_price_levels_number',
includes/functions/wcj-functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Functions.
6
  *
7
- * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -242,6 +242,38 @@ if ( ! function_exists( 'wcj_get_current_currency_code' ) ) {
242
  }
243
  }
244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  if ( ! function_exists( 'wcj_get_currency_exchange_rate' ) ) {
246
  /**
247
  * wcj_get_currency_exchange_rate.
@@ -563,7 +595,7 @@ if ( ! function_exists( 'wcj_is_product_wholesale_enabled_per_product' ) ) {
563
  /**
564
  * wcj_is_product_wholesale_enabled.
565
  *
566
- * @version 2.5.0
567
  */
568
  if ( ! function_exists( 'wcj_is_product_wholesale_enabled' ) ) {
569
  function wcj_is_product_wholesale_enabled( $product_id ) {
@@ -571,15 +603,29 @@ if ( ! function_exists( 'wcj_is_product_wholesale_enabled' ) ) {
571
  if ( wcj_is_product_wholesale_enabled_per_product( $product_id ) ) {
572
  return true;
573
  } else {
 
574
  $products_to_include = get_option( 'wcj_wholesale_price_products_to_include', array() );
575
  if ( empty ( $products_to_include ) ) {
576
- return true;
 
 
 
 
 
 
577
  }
578
- foreach ( $products_to_include as $id ) {
579
- if ( $product_id == $id ) {
580
- return true;
 
 
 
 
 
 
581
  }
582
  }
 
583
  }
584
  }
585
  return false;
4
  *
5
  * The WooCommerce Jetpack Functions.
6
  *
7
+ * @version 2.5.4
8
  * @author Algoritmika Ltd.
9
  */
10
 
242
  }
243
  }
244
 
245
+ if ( ! function_exists( 'wcj_get_currency_by_country' ) ) {
246
+ /**
247
+ * wcj_get_currency_by_country.
248
+ *
249
+ * @version 2.5.4
250
+ * @since 2.5.4
251
+ */
252
+ function wcj_get_currency_by_country( $country_code ) {
253
+ $currency_code = '';
254
+ for ( $i = 1; $i <= apply_filters( 'wcj_get_option_filter', 1, get_option( 'wcj_price_by_country_total_groups_number', 1 ) ); $i++ ) {
255
+ switch ( get_option( 'wcj_price_by_country_selection', 'comma_list' ) ) {
256
+ case 'comma_list':
257
+ $country_exchange_rate_group = get_option( 'wcj_price_by_country_exchange_rate_countries_group_' . $i );
258
+ $country_exchange_rate_group = str_replace( ' ', '', $country_exchange_rate_group );
259
+ $country_exchange_rate_group = explode( ',', $country_exchange_rate_group );
260
+ break;
261
+ case 'multiselect':
262
+ $country_exchange_rate_group = get_option( 'wcj_price_by_country_countries_group_' . $i );
263
+ break;
264
+ case 'chosen_select':
265
+ $country_exchange_rate_group = get_option( 'wcj_price_by_country_countries_group_chosen_select_' . $i );
266
+ break;
267
+ }
268
+ if ( in_array( $country_code, $country_exchange_rate_group ) ) {
269
+ $currency_code = get_option( 'wcj_price_by_country_exchange_rate_currency_group_' . $i );
270
+ break;
271
+ }
272
+ }
273
+ return ( '' == $currency_code ) ? get_option( 'woocommerce_currency' ) : $currency_code;
274
+ }
275
+ }
276
+
277
  if ( ! function_exists( 'wcj_get_currency_exchange_rate' ) ) {
278
  /**
279
  * wcj_get_currency_exchange_rate.
595
  /**
596
  * wcj_is_product_wholesale_enabled.
597
  *
598
+ * @version 2.5.4
599
  */
600
  if ( ! function_exists( 'wcj_is_product_wholesale_enabled' ) ) {
601
  function wcj_is_product_wholesale_enabled( $product_id ) {
603
  if ( wcj_is_product_wholesale_enabled_per_product( $product_id ) ) {
604
  return true;
605
  } else {
606
+ $products_to_include_passed = false;
607
  $products_to_include = get_option( 'wcj_wholesale_price_products_to_include', array() );
608
  if ( empty ( $products_to_include ) ) {
609
+ $products_to_include_passed = true;
610
+ } else {
611
+ foreach ( $products_to_include as $id ) {
612
+ if ( $product_id == $id ) {
613
+ $products_to_include_passed = true;
614
+ }
615
+ }
616
  }
617
+ $products_to_exclude_passed = false;
618
+ $products_to_exclude = get_option( 'wcj_wholesale_price_products_to_exclude', array() );
619
+ if ( empty ( $products_to_exclude ) ) {
620
+ $products_to_exclude_passed = true;
621
+ } else {
622
+ foreach ( $products_to_exclude as $id ) {
623
+ if ( $product_id == $id ) {
624
+ $products_to_exclude_passed = false;
625
+ }
626
  }
627
  }
628
+ return ( $products_to_include_passed && $products_to_exclude_passed );
629
  }
630
  }
631
  return false;
includes/js/eu-vat-number.js CHANGED
@@ -1,3 +1,8 @@
 
 
 
 
 
1
  jQuery( function( $ ) {
2
  $( 'form.checkout' ).on( 'blur change', 'input[name="billing_eu_vat_number"]', function(event) {
3
  // $( 'form.checkout' ).on( 'click', 'a[name="billing_eu_vat_number_verify"]', function(event) {
@@ -8,22 +13,18 @@ jQuery( function( $ ) {
8
  var wcj_eu_vat_number_to_check = $('input[name="billing_eu_vat_number"]').val();
9
  if (''!=wcj_eu_vat_number_to_check) {
10
  //Validating EU VAT Number through AJAX call
11
- $.ajax({
12
- url: '/?wcj_validate_eu_vat_number',
13
- data: 'wcj_eu_vat_number_to_check='+wcj_eu_vat_number_to_check,
14
- type: 'GET',
15
- success: function (response) {
16
- if ('1'==response) {
17
- $('p[id="billing_eu_vat_number_field"]').addClass('woocommerce-validated');
18
- } else {
19
- $('p[id="billing_eu_vat_number_field"]').addClass('woocommerce-invalid');
20
- }
21
- console.log('triggering update_checkout');//TODO: double update_checkout issue.
22
- $('body').trigger('update_checkout');
23
- },
24
- error: function (e) {
25
- console.log(e.message);
26
  }
 
 
27
  });
28
  } else {
29
  //Empty
1
+ /**
2
+ * eu-vat-number.
3
+ *
4
+ * version 2.5.4
5
+ */
6
  jQuery( function( $ ) {
7
  $( 'form.checkout' ).on( 'blur change', 'input[name="billing_eu_vat_number"]', function(event) {
8
  // $( 'form.checkout' ).on( 'click', 'a[name="billing_eu_vat_number_verify"]', function(event) {
13
  var wcj_eu_vat_number_to_check = $('input[name="billing_eu_vat_number"]').val();
14
  if (''!=wcj_eu_vat_number_to_check) {
15
  //Validating EU VAT Number through AJAX call
16
+ var data = {
17
+ 'action': 'wcj_validate_eu_vat_number',
18
+ 'wcj_eu_vat_number_to_check': wcj_eu_vat_number_to_check,
19
+ };
20
+ jQuery.post(ajax_object.ajax_url, data, function(response) {
21
+ if ('1'==response) {
22
+ $('p[id="billing_eu_vat_number_field"]').addClass('woocommerce-validated');
23
+ } else {
24
+ $('p[id="billing_eu_vat_number_field"]').addClass('woocommerce-invalid');
 
 
 
 
 
 
25
  }
26
+ console.log('triggering update_checkout');//TODO: double update_checkout issue.
27
+ $('body').trigger('update_checkout');
28
  });
29
  } else {
30
  //Empty
includes/js/wcj-wSelect.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /**
2
+ * wcj-wSelect.
3
+ *
4
+ * version 2.5.4
5
+ * since 2.5.4
6
+ */
7
+ jQuery('select#wcj-country').wSelect();
includes/lib/wSelect/img/arrow-down.png ADDED
Binary file
includes/lib/wSelect/wSelect.css ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /***********************************
2
+ * Layout
3
+ ***********************************/
4
+ .wSelect-el {
5
+ width: 0px;
6
+ height: 0px;
7
+ padding: 0px;
8
+ margin: 0px;
9
+ border: none;
10
+ overflow: hidden;
11
+ }
12
+ .wSelect {
13
+ position: relative;
14
+ display: inline-block;
15
+ *display: inline;
16
+ zoom: 1;
17
+ vertical-align: middle;
18
+ cursor: pointer;
19
+ -webkit-touch-callout: none;
20
+ -webkit-user-select: none;
21
+ -khtml-user-select: none;
22
+ -moz-user-select: none;
23
+ -ms-user-select: none;
24
+ user-select: none;
25
+ }
26
+ .wSelect-arrow {
27
+ position: absolute;
28
+ width: 30px;
29
+ right: 0px;
30
+ top: 0px;
31
+ height: 100%;
32
+ background-repeat: no-repeat;
33
+ background-position: 0px center;
34
+ }
35
+ .wSelect-hover .wSelect-arrow,
36
+ .wSelect-active .wSelect-arrow {
37
+ background-position: -30px center;
38
+ }
39
+ .wSelect.wSelect-multiple {
40
+ overflow: hidden;
41
+ }
42
+ .wSelect-selected {
43
+ margin: 0px 35px 0px 5px;
44
+ padding: 5px 0;
45
+ overflow: hidden;
46
+ white-space: nowrap;
47
+ background-repeat: no-repeat;
48
+ background-position: 0 center;
49
+ }
50
+ .wSelect-options-holder {
51
+ position: absolute;
52
+ display: none;
53
+ left: 0px;
54
+ z-index: 200;
55
+ overflow: hidden;
56
+ }
57
+ .wSelect-multiple .wSelect-options-holder {
58
+ position: relative !important;
59
+ display: block !important;
60
+ top: auto !important;
61
+ z-index: auto !important;
62
+ border: none !important;
63
+ }
64
+ .wSelect-options {
65
+ overflow-y: scroll;
66
+ overflow-x: hidden;
67
+ }
68
+ .wSelect-option {
69
+ background-repeat: no-repeat;
70
+ background-position: 5px center;
71
+ margin-bottom: 1px;
72
+ cursor: pointer;
73
+ }
74
+ .wSelect-option-last {
75
+ margin-bottom: 0px;
76
+ }
77
+ .wSelect-option-value {
78
+ margin: 0 5px;
79
+ padding: 5px 0;
80
+ background-repeat: no-repeat;
81
+ background-position: 0 center;
82
+ white-space: nowrap;
83
+ overflow: hidden;
84
+ }
85
+ .wSelect-option-disabled .wSelect-option-value {
86
+ filter: alpha(opacity=20);
87
+ opacity: 0.2;
88
+ }
89
+ .wSelect-option-icon {
90
+ padding-left: 20px;
91
+ }
92
+
93
+ /***********************************
94
+ * Theme - classic
95
+ ***********************************/
96
+ .wSelect-theme-classic.wSelect {
97
+ border: solid #CCC 1px;
98
+ color: #555;
99
+ background-color: #FAFAFA;
100
+ font-size: 12px;
101
+ font-family: verdana;
102
+ line-height: 20px;
103
+ min-width: 100px;
104
+ max-width: 300px;
105
+ margin-bottom: 7px;
106
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
107
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
108
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
109
+ border-radius: 5px;
110
+ -webkit-border-radius: 5px;
111
+ -moz-border-radius: 5px;
112
+ }
113
+ .wSelect-arrow {
114
+ background-image: url('./img/arrow-down.png');
115
+ }
116
+ .wSelect-theme-classic.wSelect-hover,
117
+ .wSelect-theme-classic.wSelect-active {
118
+ border-color: rgb(82, 168, 236);
119
+ border-color: rgba(82, 168, 236, 0.8);
120
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
121
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
122
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
123
+ }
124
+ .wSelect-theme-classic .wSelect-options-holder {
125
+ background-color: #FAFAFA;
126
+ border: solid #CACACA 1px;
127
+ border-radius: 5px;
128
+ -webkit-border-radius: 5px;
129
+ -moz-border-radius: 5px;
130
+ min-width: 100px;
131
+ max-width: 300px;
132
+ }
133
+ .wSelect-theme-classic .wSelect-options {
134
+ border: solid #FAFAFA 1px;
135
+ border-radius: 4px;
136
+ -webkit-border-radius: 4px;
137
+ -moz-border-radius: 4px;
138
+ }
139
+ .wSelect-theme-classic .wSelect-option {
140
+ background-color: #FFF;
141
+ color: #333;
142
+ }
143
+ .wSelect-theme-classic .wSelect-option-disabled {
144
+ background-color: #FFF !important;
145
+ color: #333 !important;
146
+ }
147
+ .wSelect-theme-classic .wSelect-option-selected,
148
+ .wSelect-theme-classic .wSelect-option:hover {
149
+ background-color: #99AAFF;
150
+ color: #FAFAFA;
151
+ }
152
+
153
+ /***********************************
154
+ * Labels
155
+ ***********************************/
156
+ .wLabel-top,
157
+ .wLabel-left,
158
+ .wLabel-left-top {
159
+ vertical-align: middle;
160
+ font-size: 10px;
161
+ line-height: 16px;
162
+ color: #999;
163
+ display: block;
164
+ margin: 5px 0 3px 3px;
165
+ }
166
+ .wLabel-left-top {
167
+ vertical-align: top;
168
+ }
169
+ @media screen and (min-width: 600px) {
170
+ .wLabel-left,
171
+ .wLabel-left-top {
172
+ display: inline-block;
173
+ *display: inline;
174
+ zoom: 1;
175
+ width: 70px;
176
+ text-align: right;
177
+ margin: 0 0 7px 0;
178
+ }
179
+ }
includes/lib/wSelect/wSelect.min.js ADDED
@@ -0,0 +1 @@
 
1
+ /*! wSelect - v1.2.1 - 2014-04-08 */!function(a){function b(b,c){this.$el=a(b),this.id=Math.random(),this.options=c,this.multiple=this.$el.prop("multiple"),this.activeOpt=null,this.widthSet=!1,this.generate()}function c(b,c){this.$el=a(b),this.wSelect=c}b.prototype={generate:function(){if(!this.$select){var b=this;this.$select=a('<div class="wSelect"><div class="wSelect-arrow"></div></div>'),this.$optionsHolder=a('<div class="wSelect-options-holder"></div>'),this.$options=a('<div class="wSelect-options"></div>'),a.support.placeholder||this.$select.css("zIndex",100-this.$el.index());var c=function(c){c.stopPropagation(),a("select").each(function(){var c=a(this).data("wSelect");c&&c.id!==b.id&&(c.multiple||c.$optionsHolder.hide(),c.onBlur())}),b.multiple||b.onClick(c),b.$el.focus()};this.multiple?(this.$select.addClass("wSelect-multiple"),this.$optionsHolder.click(c)):(this.$selected=a('<div class="wSelect-selected"></div>'),this.$select.append(this.$selected),this.$select.click(c),this.$optionsHolder.click(function(a){a.stopPropagation(),b.$el.focus()})),this.$select.hover(function(){b.onFocus("hover")},function(){b.onBlur("hover")}),this.$el.addClass("wSelect-el").change(function(){b.change()}).focus(function(){b.onFocus()}).keydown(function(a){b.keydown(a)}).keyup(function(a){b.keyup(a)}),a(document).click(function(){b.multiple||b.$optionsHolder.hide(),b.onBlur()}),this.widthSet=this.$select.width()>0,this.setTheme(this.options.theme),this.setSize(this.options.size),this.reset(),this.$optionsHolder.append(this.$options),this.$select.append(this.$optionsHolder),this.$el.after(this.$select)}return this.$select},reset:function(){var b=this;this.$options.children().remove(),this.$el.children().each(function(){var d=new c(this,b);a.data(this,"wSelect-option",d),b.$options.append(d.generate())}),this.$options.children().removeClass("wSelect-option-last").last().addClass("wSelect-option-last"),this.setSize(this.options.size)},change:function(){this.$options.children().removeClass("wSelect-option-selected wSelect-option-active"),this.$el.children(":selected").each(function(){a(this).data("wSelect-option").select()})},keydown:function(a){9===a.keyCode&&(this.$optionsHolder.hide(),this.onBlur())},keyup:function(a){if(13===a.keyCode)this.$optionsHolder.hide();else if(a.keyCode>=37&&a.keyCode<=40){this.change();var b=this.$options.find(".wSelect-option-selected:last"),c=this.$options.scrollTop(),d=b.position().top+c,e=this.$options.height(),f=b.outerHeight(!0);0>d-c?this.$options.scrollTop(d):d+f-c>e&&this.$options.scrollTop(d-e+f)}},onClick:function(){if(!this.$optionsHolder.is(":visible")){var b=this.$select.offset().top-a(window).scrollTop(),c=this.$optionsHolder.outerHeight(),d=b-c,e=a(window).height()-(b+this.$select.outerHeight()+c+5),f=e>0||e>d?this.$select.height():-c;this.$optionsHolder.css("top",f)}this.$optionsHolder.toggle()},onFocus:function(a){a=a||"active",this.options.highlight&&this.$select.addClass("wSelect-"+a)},onBlur:function(a){a=a||"active",this.options.highlight&&this.$select.removeClass("wSelect-"+a)},setTheme:function(a){this.$select.attr("class",this.$select.attr("class").replace(/wSelect-theme-.+\s|wSelect-theme-.+$/,"")),this.$select.addClass("wSelect-theme-"+a)},setSize:function(b){var c,d=this.$options.children(":first").clone().css({position:"absolute",left:-1e4}),e=this.$el.children().length;a("body").append(d),c=d.outerHeight(!0),d.remove(),!this.multiple&&b>e&&(b=e),this.$options.height(c*b-1)}},c.prototype={generate:function(){var b=this;if(!this.$option){var c=this.$el.attr("data-icon");this.$option=a('<div class="wSelect-option"></div>'),this.$value=a('<div class="wSelect-option-value"></div>'),this.$option.append(this.$value),"string"==typeof c&&(this.$value.addClass("wSelect-option-icon"),this.$value.css("backgroundImage","url("+c+")"))}return this.$el.prop("selected")&&this.select(),this.$el.prop("disabled")?this.$option.addClass("wSelect-option-disabled"):(this.$option.removeClass("wSelect-option-disabled"),this.$option.unbind("click").click(function(a){b.onClick(a)})),this.$value.html(this.$el.html()),this.setWidth(),this.$option},select:function(){if(this.wSelect.activeOpt||(this.wSelect.activeOpt=this),!this.wSelect.multiple){var a=this.$el.attr("data-icon");"string"==typeof a?(this.wSelect.$selected.addClass("wSelect-option-icon"),this.wSelect.$selected.css("backgroundImage","url("+a+")")):(this.wSelect.$selected.removeClass("wSelect-option-icon"),this.wSelect.$selected.css("backgroundImage","")),this.wSelect.$selected.html(this.$el.html())}this.$option.addClass("wSelect-option-selected")},onClick:function(b){var c=null;if(this.wSelect.multiple&&(b.ctrlKey||b.shiftKey)){if(b.ctrlKey||!this.wSelect.activeOpt){c=this.wSelect.$el.val()||[];var d=this.$el.val(),e=a.inArray(d,c);-1===e?(c.push(this.$el.val()),this.wSelect.activeOpt=this):c.splice(e,1)}else if(b.shiftKey){var f=this.wSelect.activeOpt.$el.index(),g=this.$el.index(),h=0,i=0,j=null;g>f?(h=f,i=g):(h=g,i=f),c=[];for(var k=h;i>=k;k++)j=this.wSelect.$el.children(":eq("+k+")"),j.is(":not(:disabled)")&&c.push(j.val())}}else c=this.$el.val(),this.wSelect.$optionsHolder.hide(),this.wSelect.activeOpt=this;this.wSelect.$el.val(c).change()},setWidth:function(){if(this.wSelect.multiple||this.wSelect.widthSet)return!0;this.$option.hide().appendTo("body");var a=this.$option.width();a>this.wSelect.$select.width()&&this.wSelect.$select.width(a),this.$option.detach().show()}},a.support.placeholder="placeholder"in document.createElement("input"),a.fn.wSelect=function(c,d){function e(d){var e=a.data(d,"wSelect");if(!e){var f=jQuery.extend(!0,{},c);f.size=a(d).prop("size")||f.size,e=new b(d,f),a.data(d,"wSelect",e)}return e}if("string"==typeof c){var f=[],g=this.each(function(){var b=a(this).data("wSelect");if(b){var e=(d?"set":"get")+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase();b[c]?b[c].apply(b,[d]):d?(b[e]&&b[e].apply(b,[d]),b.options[c]&&(b.options[c]=d)):b[e]?f.push(b[e].apply(b,[d])):b.options[c]?f.push(b.options[c]):f.push(null)}});return 1===f.length?f[0]:f.length>0?f:g}return c=a.extend({},a.fn.wSelect.defaults,c),this.each(function(){e(this)})},a.fn.wSelect.defaults={theme:"classic",size:"4",highlight:!0}}(jQuery);
includes/price-by-country/class-wcj-price-by-country-core.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Price by Country Core class.
6
  *
7
- * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -17,19 +17,17 @@ class WCJ_Price_by_Country_Core {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.5.3
21
  */
22
  public function __construct() {
23
  $this->customer_country_group_id = null;
24
- add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol' ), PHP_INT_MAX - 1, 2 ); // so early because of price filter widget
25
- // $this->add_hooks();
26
- add_action( 'init', array( $this, 'add_hooks' ) );
27
  }
28
 
29
  /**
30
  * add_hooks.
31
  *
32
- * @version 2.5.3
33
  */
34
  function add_hooks() {
35
 
@@ -50,6 +48,11 @@ class WCJ_Price_by_Country_Core {
50
  }
51
  }
52
 
 
 
 
 
 
53
  // Price hooks
54
  add_filter( 'woocommerce_get_price', array( $this, 'change_price_by_country' ), PHP_INT_MAX - 1, 2 );
55
  add_filter( 'woocommerce_get_sale_price', array( $this, 'change_price_by_country' ), PHP_INT_MAX - 1, 2 );
@@ -66,7 +69,7 @@ class WCJ_Price_by_Country_Core {
66
  add_filter( 'woocommerce_get_price_excluding_tax', array( $this, 'change_price_by_country_grouped' ), PHP_INT_MAX - 1, 3 );
67
 
68
  // Currency hooks
69
- // add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol' ), PHP_INT_MAX - 1, 2 );
70
  add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX - 1, 1 );
71
 
72
  // Shipping
@@ -79,6 +82,18 @@ class WCJ_Price_by_Country_Core {
79
  }
80
  }
81
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  /**
83
  * price_filter_meta_query.
84
  *
@@ -183,7 +198,7 @@ class WCJ_Price_by_Country_Core {
183
  /**
184
  * get_customer_country_group_id.
185
  *
186
- * @version 2.5.2
187
  */
188
  public function get_customer_country_group_id() {
189
 
@@ -193,9 +208,9 @@ class WCJ_Price_by_Country_Core {
193
  }
194
 
195
  // We already know the group - nothing to calculate - return group
196
- if ( null != $this->customer_country_group_id && $this->customer_country_group_id > 0 ) {
197
  return $this->customer_country_group_id;
198
- }
199
 
200
  // Get the country
201
  if ( isset( $_GET['country'] ) && '' != $_GET['country'] && wcj_is_user_role( 'administrator' ) ) {
4
  *
5
  * The WooCommerce Jetpack Price by Country Core class.
6
  *
7
+ * @version 2.5.4
8
  * @author Algoritmika Ltd.
9
  */
10
 
17
  /**
18
  * Constructor.
19
  *
20
+ * @version 2.5.4
21
  */
22
  public function __construct() {
23
  $this->customer_country_group_id = null;
24
+ $this->add_hooks();
 
 
25
  }
26
 
27
  /**
28
  * add_hooks.
29
  *
30
+ * @version 2.5.4
31
  */
32
  function add_hooks() {
33
 
48
  }
49
  }
50
 
51
+ // Select with flags
52
+ if ( 'yes' === get_option( 'wcj_price_by_country_jquery_wselect_enabled', 'no' ) ) {
53
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_wselect_scripts' ) );
54
+ }
55
+
56
  // Price hooks
57
  add_filter( 'woocommerce_get_price', array( $this, 'change_price_by_country' ), PHP_INT_MAX - 1, 2 );
58
  add_filter( 'woocommerce_get_sale_price', array( $this, 'change_price_by_country' ), PHP_INT_MAX - 1, 2 );
69
  add_filter( 'woocommerce_get_price_excluding_tax', array( $this, 'change_price_by_country_grouped' ), PHP_INT_MAX - 1, 3 );
70
 
71
  // Currency hooks
72
+ add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol' ), PHP_INT_MAX - 1, 2 );
73
  add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX - 1, 1 );
74
 
75
  // Shipping
82
  }
83
  }
84
 
85
+ /**
86
+ * enqueue_wselect_scripts.
87
+ *
88
+ * @version 2.5.4
89
+ * @since 2.5.4
90
+ */
91
+ function enqueue_wselect_scripts() {
92
+ wp_enqueue_style( 'wcj-wSelect-style', wcj_plugin_url() . '/includes/lib/wSelect/wSelect.css' );
93
+ wp_enqueue_script( 'wcj-wSelect', wcj_plugin_url() . '/includes/lib/wSelect/wSelect.min.js', array(), false, true );
94
+ wp_enqueue_script( 'wcj-wcj-wSelect', wcj_plugin_url() . '/includes/js/wcj-wSelect.js', array(), false, true );
95
+ }
96
+
97
  /**
98
  * price_filter_meta_query.
99
  *
198
  /**
199
  * get_customer_country_group_id.
200
  *
201
+ * @version 2.5.4
202
  */
203
  public function get_customer_country_group_id() {
204
 
208
  }
209
 
210
  // We already know the group - nothing to calculate - return group
211
+ /* if ( null != $this->customer_country_group_id && $this->customer_country_group_id > 0 ) {
212
  return $this->customer_country_group_id;
213
+ } */
214
 
215
  // Get the country
216
  if ( isset( $_GET['country'] ) && '' != $_GET['country'] && wcj_is_user_role( 'administrator' ) ) {
includes/shortcodes/class-wcj-general-shortcodes.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack General Shortcodes class.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -17,7 +17,7 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.4.8
21
  */
22
  public function __construct() {
23
 
@@ -38,15 +38,16 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
38
  );
39
 
40
  $this->the_atts = array(
41
- 'date_format' => get_option( 'date_format' ),
42
- 'lang' => '',
43
- 'form_method' => 'post',//'get',
44
- 'class' => '',
45
- 'style' => '',
46
- 'countries' => '',
47
- 'currencies' => '',
48
- 'content' => '',
49
- 'heading_format' => 'from %level_qty% pcs.',
 
50
  );
51
 
52
  parent::__construct();
@@ -225,15 +226,15 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
225
  /**
226
  * wcj_country_select_drop_down_list.
227
  *
228
- * @version 2.4.0
229
  */
230
  function wcj_country_select_drop_down_list( $atts, $content ) {
231
 
232
  $html = '';
233
 
234
- $form_method = $atts['form_method'];//get_option( 'wcj_price_by_country_country_selection_box_method', 'get' );
235
- $select_class = $atts['class'];//get_option( 'wcj_price_by_country_country_selection_box_class', '' );
236
- $select_style = $atts['style'];//get_option( 'wcj_price_by_country_country_selection_box_style', '' );
237
 
238
  $html .= '<form action="" method="' . $form_method . '">';
239
 
@@ -258,14 +259,34 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
258
  } */
259
  $selected_country = ( isset( $_SESSION[ 'wcj-country' ] ) ) ? $_SESSION[ 'wcj-country' ] : '';
260
 
 
 
 
 
261
  if ( empty( $shortcode_countries ) ) {
262
  foreach ( $countries as $country_code => $country_name ) {
263
- $html .= '<option value="' . $country_code . '" ' . selected( $country_code, $selected_country, false ) . '>' . $country_name . '</option>';
 
 
 
 
 
 
 
 
264
  }
265
  } else {
266
  foreach ( $shortcode_countries as $country_code ) {
267
  if ( isset( $countries[ $country_code ] ) ) {
268
- $html .= '<option value="' . $country_code . '" ' . selected( $country_code, $selected_country, false ) . '>' . $countries[ $country_code ] . '</option>';
 
 
 
 
 
 
 
 
269
  }
270
  }
271
  }
4
  *
5
  * The WooCommerce Jetpack General Shortcodes class.
6
  *
7
+ * @version 2.5.4
8
  * @author Algoritmika Ltd.
9
  */
10
 
17
  /**
18
  * Constructor.
19
  *
20
+ * @version 2.5.4
21
  */
22
  public function __construct() {
23
 
38
  );
39
 
40
  $this->the_atts = array(
41
+ 'date_format' => get_option( 'date_format' ),
42
+ 'lang' => '',
43
+ 'form_method' => 'post',//'get',
44
+ 'class' => '',
45
+ 'style' => '',
46
+ 'countries' => '',
47
+ 'currencies' => '',
48
+ 'content' => '',
49
+ 'heading_format' => 'from %level_qty% pcs.',
50
+ 'replace_with_currency' => 'no',
51
  );
52
 
53
  parent::__construct();
226
  /**
227
  * wcj_country_select_drop_down_list.
228
  *
229
+ * @version 2.5.4
230
  */
231
  function wcj_country_select_drop_down_list( $atts, $content ) {
232
 
233
  $html = '';
234
 
235
+ $form_method = $atts['form_method']; // get_option( 'wcj_price_by_country_country_selection_box_method', 'get' );
236
+ $select_class = $atts['class']; // get_option( 'wcj_price_by_country_country_selection_box_class', '' );
237
+ $select_style = $atts['style']; // get_option( 'wcj_price_by_country_country_selection_box_style', '' );
238
 
239
  $html .= '<form action="" method="' . $form_method . '">';
240
 
259
  } */
260
  $selected_country = ( isset( $_SESSION[ 'wcj-country' ] ) ) ? $_SESSION[ 'wcj-country' ] : '';
261
 
262
+ if ( 'yes' === $atts['replace_with_currency'] ) {
263
+ $currencies_names_and_symbols = wcj_get_currencies_names_and_symbols();
264
+ }
265
+
266
  if ( empty( $shortcode_countries ) ) {
267
  foreach ( $countries as $country_code => $country_name ) {
268
+
269
+ $data_icon = '';
270
+ if ( 'yes' === get_option( 'wcj_price_by_country_jquery_wselect_enabled', 'no' ) ) {
271
+ $data_icon = ' data-icon="' . wcj_plugin_url() . '/assets/images/flag-icons/' . $country_code . '.png"';
272
+ }
273
+
274
+ $option_label = ( 'yes' === $atts['replace_with_currency'] ) ? $currencies_names_and_symbols[ wcj_get_currency_by_country( $country_code ) ] : $country_name;
275
+
276
+ $html .= '<option' . $data_icon . ' value="' . $country_code . '" ' . selected( $country_code, $selected_country, false ) . '>' . $option_label . '</option>';
277
  }
278
  } else {
279
  foreach ( $shortcode_countries as $country_code ) {
280
  if ( isset( $countries[ $country_code ] ) ) {
281
+
282
+ $data_icon = '';
283
+ if ( 'yes' === get_option( 'wcj_price_by_country_jquery_wselect_enabled', 'no' ) ) {
284
+ $data_icon = ' data-icon="' . wcj_plugin_url() . '/assets/images/flag-icons/' . $country_code . '.png"';
285
+ }
286
+
287
+ $option_label = ( 'yes' === $atts['replace_with_currency'] ) ? $currencies_names_and_symbols[ wcj_get_currency_by_country( $country_code ) ] : $countries[ $country_code ];
288
+
289
+ $html .= '<option' . $data_icon . ' value="' . $country_code . '" ' . selected( $country_code, $selected_country, false ) . '>' . $option_label . '</option>';
290
  }
291
  }
292
  }
includes/shortcodes/class-wcj-orders-shortcodes.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Orders Shortcodes class.
6
  *
7
- * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -17,17 +17,15 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.5.3
21
  */
22
  public function __construct() {
23
 
24
  $this->the_shortcodes = array(
25
-
26
  'wcj_order_date',
27
  'wcj_order_time',
28
  'wcj_order_number',
29
  'wcj_order_id',
30
-
31
  'wcj_order_billing_address',
32
  'wcj_order_billing_phone',
33
  'wcj_order_checkout_field',
@@ -37,31 +35,30 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
37
  'wcj_order_custom_meta_field',
38
  'wcj_order_meta',
39
  'wcj_order_items_meta',
40
-
41
  'wcj_order_subtotal',
42
  'wcj_order_subtotal_plus_shipping',
43
  'wcj_order_total_discount',
44
  // 'wcj_order_cart_discount',
45
  'wcj_order_shipping_tax',
46
  'wcj_order_taxes_html',
 
47
  'wcj_order_total_tax',
48
  'wcj_order_total_tax_percent',
49
  'wcj_order_total',
 
 
50
  'wcj_order_currency',
51
  'wcj_order_total_in_words',
52
  'wcj_order_total_excl_tax',
53
  'wcj_order_shipping_price',
54
  'wcj_order_total_refunded',
55
-
56
  'wcj_order_total_fees',
57
  'wcj_order_total_fees_incl_tax',
58
  'wcj_order_total_fees_tax',
59
  'wcj_order_fee',
60
  'wcj_order_fees_html',
61
-
62
  'wcj_order_payment_method',
63
  'wcj_order_shipping_method',
64
-
65
  'wcj_order_items_total_weight',
66
  'wcj_order_items_total_quantity',
67
  'wcj_order_items_total_number',
@@ -480,6 +477,57 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
480
  return $this->wcj_price_shortcode( $this->the_order->get_total_refunded(), $atts );
481
  }
482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
483
  /**
484
  * wcj_order_taxes_html.
485
  *
4
  *
5
  * The WooCommerce Jetpack Orders Shortcodes class.
6
  *
7
+ * @version 2.5.4
8
  * @author Algoritmika Ltd.
9
  */
10
 
17
  /**
18
  * Constructor.
19
  *
20
+ * @version 2.5.4
21
  */
22
  public function __construct() {
23
 
24
  $this->the_shortcodes = array(
 
25
  'wcj_order_date',
26
  'wcj_order_time',
27
  'wcj_order_number',
28
  'wcj_order_id',
 
29
  'wcj_order_billing_address',
30
  'wcj_order_billing_phone',
31
  'wcj_order_checkout_field',
35
  'wcj_order_custom_meta_field',
36
  'wcj_order_meta',
37
  'wcj_order_items_meta',
 
38
  'wcj_order_subtotal',
39
  'wcj_order_subtotal_plus_shipping',
40
  'wcj_order_total_discount',
41
  // 'wcj_order_cart_discount',
42
  'wcj_order_shipping_tax',
43
  'wcj_order_taxes_html',
44
+ 'wcj_order_tax_by_class',
45
  'wcj_order_total_tax',
46
  'wcj_order_total_tax_percent',
47
  'wcj_order_total',
48
+ 'wcj_order_total_by_tax_class',
49
+ 'wcj_order_subtotal_by_tax_class',
50
  'wcj_order_currency',
51
  'wcj_order_total_in_words',
52
  'wcj_order_total_excl_tax',
53
  'wcj_order_shipping_price',
54
  'wcj_order_total_refunded',
 
55
  'wcj_order_total_fees',
56
  'wcj_order_total_fees_incl_tax',
57
  'wcj_order_total_fees_tax',
58
  'wcj_order_fee',
59
  'wcj_order_fees_html',
 
60
  'wcj_order_payment_method',
61
  'wcj_order_shipping_method',
 
62
  'wcj_order_items_total_weight',
63
  'wcj_order_items_total_quantity',
64
  'wcj_order_items_total_number',
477
  return $this->wcj_price_shortcode( $this->the_order->get_total_refunded(), $atts );
478
  }
479
 
480
+ /**
481
+ * wcj_order_subtotal_by_tax_class.
482
+ *
483
+ * @version 2.5.4
484
+ * @since 2.5.4
485
+ */
486
+ function wcj_order_subtotal_by_tax_class( $atts ) {
487
+ $subtotal_by_tax_class = 0;
488
+ $tax_class = ( 'standard' === $atts['tax_class'] ) ? '' : $atts['tax_class'];
489
+ foreach ( $this->the_order->get_items() as $item ) {
490
+ if ( $tax_class === $item['tax_class'] ) {
491
+ $subtotal_by_tax_class += $item['line_subtotal'];
492
+ }
493
+ }
494
+ return $this->wcj_price_shortcode( $subtotal_by_tax_class, $atts );
495
+ }
496
+
497
+ /**
498
+ * wcj_order_total_by_tax_class.
499
+ *
500
+ * @version 2.5.4
501
+ * @since 2.5.4
502
+ */
503
+ function wcj_order_total_by_tax_class( $atts ) {
504
+ $total_by_tax_class = 0;
505
+ $tax_class = ( 'standard' === $atts['tax_class'] ) ? '' : $atts['tax_class'];
506
+ foreach ( $this->the_order->get_items() as $item ) {
507
+ if ( $tax_class === $item['tax_class'] ) {
508
+ $total_by_tax_class += $item['line_total'];
509
+ }
510
+ }
511
+ return $this->wcj_price_shortcode( $total_by_tax_class, $atts );
512
+ }
513
+
514
+ /**
515
+ * wcj_order_tax_by_class.
516
+ *
517
+ * @version 2.5.4
518
+ * @since 2.5.4
519
+ */
520
+ function wcj_order_tax_by_class( $atts ) {
521
+ $tax_class = ( 'standard' === $atts['tax_class'] ) ? '' : $atts['tax_class'];
522
+ $total_tax_by_class = 0;
523
+ foreach ( $this->the_order->get_items() as $item ) {
524
+ if ( $tax_class === $item['tax_class'] ) {
525
+ $total_tax_by_class += $this->the_order->get_line_tax( $item );
526
+ }
527
+ }
528
+ return $this->wcj_price_shortcode( $total_tax_by_class, $atts );
529
+ }
530
+
531
  /**
532
  * wcj_order_taxes_html.
533
  *
includes/shortcodes/class-wcj-products-add-form-shortcodes.php CHANGED
@@ -4,10 +4,10 @@
4
  *
5
  * The WooCommerce Jetpack Products Add Form Shortcodes class.
6
  *
7
- * @version 2.5.2
8
  * @since 2.5.0
9
  * @author Algoritmika Ltd.
10
- * @todo refill on not validated; titles and messages; fields ids and label tags; other styling; custom fields;
11
  */
12
 
13
  if ( ! defined( 'ABSPATH' ) ) exit;
@@ -129,7 +129,7 @@ class WCJ_Products_Add_Form_Shortcodes extends WCJ_Shortcodes {
129
  /**
130
  * validate_args.
131
  *
132
- * @version 2.5.2
133
  * @since 2.5.0
134
  */
135
  function validate_args( $args, $shortcode_atts ) {
@@ -138,6 +138,15 @@ class WCJ_Products_Add_Form_Shortcodes extends WCJ_Shortcodes {
138
  $errors .= '<li>' . __( 'Title is required!', 'woocommerce-jetpack' ) . '</li>';
139
  }
140
 
 
 
 
 
 
 
 
 
 
141
  $fields = array(
142
  'desc' => __( 'Description', 'woocommerce-jetpack' ),
143
  'short_desc' => __( 'Short Description', 'woocommerce-jetpack' ),
@@ -170,7 +179,7 @@ class WCJ_Products_Add_Form_Shortcodes extends WCJ_Shortcodes {
170
  /**
171
  * wcj_product_add_new.
172
  *
173
- * @version 2.5.2
174
  * @since 2.5.0
175
  */
176
  function wcj_product_add_new( $atts ) {
@@ -180,22 +189,42 @@ class WCJ_Products_Add_Form_Shortcodes extends WCJ_Shortcodes {
180
  $input_fields_html = '';
181
  $footer_html = '';
182
 
 
 
 
 
 
 
 
 
 
 
 
183
  if ( isset( $_REQUEST['wcj_add_new_product'] ) ) {
184
- $args = array(
185
- 'title' => isset( $_REQUEST['wcj_add_new_product_title'] ) ? $_REQUEST['wcj_add_new_product_title'] : '',
186
- 'desc' => isset( $_REQUEST['wcj_add_new_product_desc'] ) ? $_REQUEST['wcj_add_new_product_desc'] : '',
187
- 'short_desc' => isset( $_REQUEST['wcj_add_new_product_short_desc'] ) ? $_REQUEST['wcj_add_new_product_short_desc'] : '',
188
- 'regular_price' => isset( $_REQUEST['wcj_add_new_product_regular_price'] ) ? $_REQUEST['wcj_add_new_product_regular_price'] : '',
189
- 'sale_price' => isset( $_REQUEST['wcj_add_new_product_sale_price'] ) ? $_REQUEST['wcj_add_new_product_sale_price'] : '',
190
- 'cats' => isset( $_REQUEST['wcj_add_new_product_cats'] ) ? $_REQUEST['wcj_add_new_product_cats'] : array(),
191
- 'tags' => isset( $_REQUEST['wcj_add_new_product_tags'] ) ? $_REQUEST['wcj_add_new_product_tags'] : array(),
192
- 'image' => isset( $_FILES['wcj_add_new_product_image'] ) ? $_FILES['wcj_add_new_product_image'] : '',
193
- );
194
  if ( true === ( $validate_args = $this->validate_args( $args, $atts ) ) ) {
195
  $result = $this->wc_add_new_product( $args, $atts );
196
- $notice_html .= ( 0 == $result )
197
- ? '<div class="woocommerce"><ul class="woocommerce-error"><li>' . __( 'Error!', 'woocommerce-jetpack' ) . '</li></ul></div>'
198
- : '<div class="woocommerce"><div class="woocommerce-message">' . __( 'Success!', 'woocommerce-jetpack' ) . '</div></div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  } else {
200
  $notice_html .= '<div class="woocommerce"><ul class="woocommerce-error">' . $validate_args . '</ul></div>';
201
  }
@@ -213,39 +242,43 @@ class WCJ_Products_Add_Form_Shortcodes extends WCJ_Shortcodes {
213
  }
214
  }
215
 
216
- $this->the_product = wc_get_product( $atts['product_id'] );
 
 
217
 
218
  $header_html .= '<h3>';
219
  $header_html .= ( 0 == $atts['product_id'] ) ? __( 'Add New Product', 'woocommerce-jetpack' ) : __( 'Edit Product', 'woocommerce-jetpack' );
220
  $header_html .= '</h3>';
221
  $header_html .= '<form method="post" action="' . remove_query_arg( array( 'wcj_edit_product_image_delete', 'wcj_delete_product' ) ) . '" enctype="multipart/form-data">'; // todo multipart only if image...
222
 
 
 
223
  $table_data = array();
224
  $input_style = 'width:100%;';
225
  $table_data[] = array(
226
- __( 'Title', 'woocommerce-jetpack' ) . '&nbsp;<abbr class="required" title="required">*</abbr>',
227
- '<input required type="text" style="' . $input_style . '" name="wcj_add_new_product_title" value="' . ( ( 0 != $atts['product_id'] ) ? $this->the_product->get_title() : '' ) . '">'
228
  );
229
  if ( 'yes' === $atts['desc_enabled'] ) {
230
  $required_html = ( 'yes' === $atts['desc_required'] ) ? ' required' : '';
231
- $required_mark_html = ( 'yes' === $atts['desc_required'] ) ? '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
232
  $table_data[] = array(
233
- __( 'Description', 'woocommerce-jetpack' ) . $required_mark_html,
234
- '<textarea' . $required_html . ' style="' . $input_style . '" name="wcj_add_new_product_desc">' . ( ( 0 != $atts['product_id'] ) ? get_post_field( 'post_content', $atts['product_id'] ) : '' ) . '</textarea>'
235
  );
236
  }
237
  if ( 'yes' === $atts['short_desc_enabled'] ) {
238
  $required_html = ( 'yes' === $atts['short_desc_required'] ) ? ' required' : '';
239
- $required_mark_html = ( 'yes' === $atts['short_desc_required'] ) ? '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
240
  $table_data[] = array(
241
- __( 'Short Description', 'woocommerce-jetpack' ) . $required_mark_html,
242
- '<textarea' . $required_html . ' style="' . $input_style . '" name="wcj_add_new_product_short_desc">' . ( ( 0 != $atts['product_id'] ) ? get_post_field( 'post_excerpt', $atts['product_id'] ) : '' ) . '</textarea>'
243
  );
244
  }
245
  if ( 'yes' === $atts['image_enabled'] ) {
246
  $required_html = ( 'yes' === $atts['image_required'] ) ? ' required' : '';
247
- $required_mark_html = ( 'yes' === $atts['image_required'] ) ? '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
248
- $new_image_field = '<input' . $required_html . ' type="file" name="wcj_add_new_product_image" accept="image/*">';
249
  if ( 0 != $atts['product_id'] ) {
250
  $the_field = ( '' == get_post_thumbnail_id( $atts['product_id'] ) ) ?
251
  $new_image_field :
@@ -254,64 +287,70 @@ class WCJ_Products_Add_Form_Shortcodes extends WCJ_Shortcodes {
254
  $the_field = $new_image_field;
255
  }
256
  $table_data[] = array(
257
- __( 'Image', 'woocommerce-jetpack' ) . $required_mark_html,
258
  $the_field
259
  );
260
  }
261
  if ( 'yes' === $atts['regular_price_enabled'] ) {
262
  $required_html = ( 'yes' === $atts['regular_price_required'] ) ? ' required' : '';
263
- $required_mark_html = ( 'yes' === $atts['regular_price_required'] ) ? '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
264
  $table_data[] = array(
265
- __( 'Regular Price', 'woocommerce-jetpack' ) . $required_mark_html,
266
- '<input' . $required_html . ' type="number" min="0" step="0.01" name="wcj_add_new_product_regular_price" value="' . ( ( 0 != $atts['product_id'] ) ? get_post_meta( $atts['product_id'], '_regular_price', true ) : '' ) . '">'
267
  );
268
  }
269
  if ( 'yes' === $atts['sale_price_enabled'] ) {
270
  $required_html = ( 'yes' === $atts['sale_price_required'] ) ? ' required' : '';
271
- $required_mark_html = ( 'yes' === $atts['sale_price_required'] ) ? '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
272
  $table_data[] = array(
273
- __( 'Sale Price', 'woocommerce-jetpack' ) . $required_mark_html,
274
- '<input' . $required_html . ' type="number" min="0" step="0.01" name="wcj_add_new_product_sale_price" value="' . ( ( 0 != $atts['product_id'] ) ? get_post_meta( $atts['product_id'], '_sale_price', true ) : '' ) . '">'
275
  );
276
  }
277
  if ( 'yes' === $atts['cats_enabled'] ) {
278
  $required_html = ( 'yes' === $atts['cats_required'] ) ? ' required' : '';
279
- $required_mark_html = ( 'yes' === $atts['cats_required'] ) ? '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
280
- $current_product_categories = ( 0 != $atts['product_id'] ) ? get_the_terms( $atts['product_id'], 'product_cat' ) : array();
281
  $product_categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
282
  $product_categories_as_select_options = '';
283
  foreach ( $product_categories as $product_category ) {
284
  $selected = '';
285
  if ( ! empty( $current_product_categories ) ) {
286
  foreach ( $current_product_categories as $current_product_category ) {
287
- $selected .= selected( $current_product_category->term_id, $product_category->term_id, false );
 
 
 
288
  }
289
  }
290
  $product_categories_as_select_options .= '<option value="' . $product_category->slug . '" ' . $selected . '>' . $product_category->name .'</option>';
291
  }
292
  $table_data[] = array(
293
- __( 'Categories', 'woocommerce-jetpack' ) . $required_mark_html,
294
- '<select' . $required_html . ' multiple style="' . $input_style . '" name="wcj_add_new_product_cats[]">' . $product_categories_as_select_options . '</select>'
295
  );
296
  }
297
  if ( 'yes' === $atts['tags_enabled'] ) {
298
  $required_html = ( 'yes' === $atts['tags_required'] ) ? ' required' : '';
299
- $required_mark_html = ( 'yes' === $atts['tags_required'] ) ? '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
300
- $current_product_tags = ( 0 != $atts['product_id'] ) ? get_the_terms( $atts['product_id'], 'product_tag' ) : array();
301
  $products_tags = get_terms( 'product_tag', 'orderby=name&hide_empty=0' );
302
  $products_tags_as_select_options = '';
303
  foreach ( $products_tags as $products_tag ) {
304
  $selected = '';
305
  if ( ! empty( $current_product_tags ) ) {
306
  foreach ( $current_product_tags as $current_product_tag ) {
307
- $selected .= selected( $current_product_tag->term_id, $products_tag->term_id, false );
 
 
 
308
  }
309
  }
310
  $products_tags_as_select_options .= '<option value="' . $products_tag->slug . '" ' . $selected . '>' . $products_tag->name .'</option>';
311
  }
312
  $table_data[] = array(
313
- __( 'Tags', 'woocommerce-jetpack' ) . $required_mark_html,
314
- '<select' . $required_html . ' multiple style="' . $input_style . '" name="wcj_add_new_product_tags[]">' . $products_tags_as_select_options . '</select>'
315
  );
316
  }
317
 
4
  *
5
  * The WooCommerce Jetpack Products Add Form Shortcodes class.
6
  *
7
+ * @version 2.5.4
8
  * @since 2.5.0
9
  * @author Algoritmika Ltd.
10
+ * @todo refill image on not validated (or after successful addition); more messages options; more styling options; custom fields;
11
  */
12
 
13
  if ( ! defined( 'ABSPATH' ) ) exit;
129
  /**
130
  * validate_args.
131
  *
132
+ * @version 2.5.4
133
  * @since 2.5.0
134
  */
135
  function validate_args( $args, $shortcode_atts ) {
138
  $errors .= '<li>' . __( 'Title is required!', 'woocommerce-jetpack' ) . '</li>';
139
  }
140
 
141
+ if ( 'yes' === get_option( 'wcj_product_by_user_require_unique_title', 'no' ) && 0 == $shortcode_atts['product_id'] ) {
142
+ if ( ! function_exists( 'post_exists' ) ) {
143
+ require_once( ABSPATH . 'wp-admin/includes/post.php' );
144
+ }
145
+ if ( post_exists( $args['title'] ) ) {
146
+ $errors .= '<li>' . __( 'Product exists!', 'woocommerce-jetpack' ) . '</li>';
147
+ }
148
+ }
149
+
150
  $fields = array(
151
  'desc' => __( 'Description', 'woocommerce-jetpack' ),
152
  'short_desc' => __( 'Short Description', 'woocommerce-jetpack' ),
179
  /**
180
  * wcj_product_add_new.
181
  *
182
+ * @version 2.5.4
183
  * @since 2.5.0
184
  */
185
  function wcj_product_add_new( $atts ) {
189
  $input_fields_html = '';
190
  $footer_html = '';
191
 
192
+ $args = array(
193
+ 'title' => isset( $_REQUEST['wcj_add_new_product_title'] ) ? $_REQUEST['wcj_add_new_product_title'] : '',
194
+ 'desc' => isset( $_REQUEST['wcj_add_new_product_desc'] ) ? $_REQUEST['wcj_add_new_product_desc'] : '',
195
+ 'short_desc' => isset( $_REQUEST['wcj_add_new_product_short_desc'] ) ? $_REQUEST['wcj_add_new_product_short_desc'] : '',
196
+ 'regular_price' => isset( $_REQUEST['wcj_add_new_product_regular_price'] ) ? $_REQUEST['wcj_add_new_product_regular_price'] : '',
197
+ 'sale_price' => isset( $_REQUEST['wcj_add_new_product_sale_price'] ) ? $_REQUEST['wcj_add_new_product_sale_price'] : '',
198
+ 'cats' => isset( $_REQUEST['wcj_add_new_product_cats'] ) ? $_REQUEST['wcj_add_new_product_cats'] : array(),
199
+ 'tags' => isset( $_REQUEST['wcj_add_new_product_tags'] ) ? $_REQUEST['wcj_add_new_product_tags'] : array(),
200
+ 'image' => isset( $_FILES['wcj_add_new_product_image'] ) ? $_FILES['wcj_add_new_product_image'] : '',
201
+ );
202
+
203
  if ( isset( $_REQUEST['wcj_add_new_product'] ) ) {
 
 
 
 
 
 
 
 
 
 
204
  if ( true === ( $validate_args = $this->validate_args( $args, $atts ) ) ) {
205
  $result = $this->wc_add_new_product( $args, $atts );
206
+ if ( 0 == $result ) {
207
+ // Error
208
+ $notice_html .= '<div class="woocommerce"><ul class="woocommerce-error"><li>' . __( 'Error!', 'woocommerce-jetpack' ) . '</li></ul></div>';
209
+ } else {
210
+ // Success
211
+ if ( 0 == $atts['product_id'] ) {
212
+ $notice_html .= '<div class="woocommerce"><div class="woocommerce-message">' .
213
+ str_replace(
214
+ '%product_title%',
215
+ $args['title'],
216
+ get_option( 'wcj_product_by_user_message_product_successfully_added', __( '"%product_title%" successfully added!', 'woocommerce-jetpack' ) ) ) .
217
+ '</div></div>';
218
+ } else {
219
+ $notice_html .= '<div class="woocommerce"><div class="woocommerce-message">' .
220
+ str_replace(
221
+ '%product_title%',
222
+ $args['title'],
223
+ get_option( 'wcj_product_by_user_message_product_successfully_edited', __( '"%product_title%" successfully edited!', 'woocommerce-jetpack' ) ) ) .
224
+ '</div></div>';
225
+ }
226
+ // $atts['product_id'] = $result;
227
+ }
228
  } else {
229
  $notice_html .= '<div class="woocommerce"><ul class="woocommerce-error">' . $validate_args . '</ul></div>';
230
  }
242
  }
243
  }
244
 
245
+ if ( 0 != $atts['product_id'] ) {
246
+ $this->the_product = wc_get_product( $atts['product_id'] );
247
+ }
248
 
249
  $header_html .= '<h3>';
250
  $header_html .= ( 0 == $atts['product_id'] ) ? __( 'Add New Product', 'woocommerce-jetpack' ) : __( 'Edit Product', 'woocommerce-jetpack' );
251
  $header_html .= '</h3>';
252
  $header_html .= '<form method="post" action="' . remove_query_arg( array( 'wcj_edit_product_image_delete', 'wcj_delete_product' ) ) . '" enctype="multipart/form-data">'; // todo multipart only if image...
253
 
254
+ $required_mark_html_template = '&nbsp;<abbr class="required" title="required">*</abbr>';
255
+
256
  $table_data = array();
257
  $input_style = 'width:100%;';
258
  $table_data[] = array(
259
+ '<label for="wcj_add_new_product_title">' . __( 'Title', 'woocommerce-jetpack' ) . $required_mark_html_template . '</label>',
260
+ '<input required type="text" style="' . $input_style . '" id="wcj_add_new_product_title" name="wcj_add_new_product_title" value="' . ( ( 0 != $atts['product_id'] ) ? $this->the_product->get_title() : $args['title'] ) . '">'
261
  );
262
  if ( 'yes' === $atts['desc_enabled'] ) {
263
  $required_html = ( 'yes' === $atts['desc_required'] ) ? ' required' : '';
264
+ $required_mark_html = ( 'yes' === $atts['desc_required'] ) ? $required_mark_html_template : '';
265
  $table_data[] = array(
266
+ '<label for="wcj_add_new_product_desc">' . __( 'Description', 'woocommerce-jetpack' ) . $required_mark_html . '</label>',
267
+ '<textarea' . $required_html . ' style="' . $input_style . '" id="wcj_add_new_product_desc" name="wcj_add_new_product_desc">' . ( ( 0 != $atts['product_id'] ) ? get_post_field( 'post_content', $atts['product_id'] ) : $args['desc'] ) . '</textarea>'
268
  );
269
  }
270
  if ( 'yes' === $atts['short_desc_enabled'] ) {
271
  $required_html = ( 'yes' === $atts['short_desc_required'] ) ? ' required' : '';
272
+ $required_mark_html = ( 'yes' === $atts['short_desc_required'] ) ? $required_mark_html_template : '';
273
  $table_data[] = array(
274
+ '<label for="wcj_add_new_product_short_desc">' . __( 'Short Description', 'woocommerce-jetpack' ) . $required_mark_html . '</label>',
275
+ '<textarea' . $required_html . ' style="' . $input_style . '" id="wcj_add_new_product_short_desc" name="wcj_add_new_product_short_desc">' . ( ( 0 != $atts['product_id'] ) ? get_post_field( 'post_excerpt', $atts['product_id'] ) : $args['short_desc'] ) . '</textarea>'
276
  );
277
  }
278
  if ( 'yes' === $atts['image_enabled'] ) {
279
  $required_html = ( 'yes' === $atts['image_required'] ) ? ' required' : '';
280
+ $required_mark_html = ( 'yes' === $atts['image_required'] ) ? $required_mark_html_template : '';
281
+ $new_image_field = '<input' . $required_html . ' type="file" id="wcj_add_new_product_image" name="wcj_add_new_product_image" accept="image/*">';
282
  if ( 0 != $atts['product_id'] ) {
283
  $the_field = ( '' == get_post_thumbnail_id( $atts['product_id'] ) ) ?
284
  $new_image_field :
287
  $the_field = $new_image_field;
288
  }
289
  $table_data[] = array(
290
+ '<label for="wcj_add_new_product_image">' . __( 'Image', 'woocommerce-jetpack' ) . $required_mark_html . '</label>',
291
  $the_field
292
  );
293
  }
294
  if ( 'yes' === $atts['regular_price_enabled'] ) {
295
  $required_html = ( 'yes' === $atts['regular_price_required'] ) ? ' required' : '';
296
+ $required_mark_html = ( 'yes' === $atts['regular_price_required'] ) ? $required_mark_html_template : '';
297
  $table_data[] = array(
298
+ '<label for="wcj_add_new_product_regular_price">' . __( 'Regular Price', 'woocommerce-jetpack' ) . $required_mark_html . '</label>',
299
+ '<input' . $required_html . ' type="number" min="0" step="0.01" id="wcj_add_new_product_regular_price" name="wcj_add_new_product_regular_price" value="' . ( ( 0 != $atts['product_id'] ) ? get_post_meta( $atts['product_id'], '_regular_price', true ) : $args['regular_price'] ) . '">'
300
  );
301
  }
302
  if ( 'yes' === $atts['sale_price_enabled'] ) {
303
  $required_html = ( 'yes' === $atts['sale_price_required'] ) ? ' required' : '';
304
+ $required_mark_html = ( 'yes' === $atts['sale_price_required'] ) ? $required_mark_html_template : '';
305
  $table_data[] = array(
306
+ '<label for="wcj_add_new_product_sale_price">' . __( 'Sale Price', 'woocommerce-jetpack' ) . $required_mark_html . '</label>',
307
+ '<input' . $required_html . ' type="number" min="0" step="0.01" id="wcj_add_new_product_sale_price" name="wcj_add_new_product_sale_price" value="' . ( ( 0 != $atts['product_id'] ) ? get_post_meta( $atts['product_id'], '_sale_price', true ) : $args['sale_price'] ) . '">'
308
  );
309
  }
310
  if ( 'yes' === $atts['cats_enabled'] ) {
311
  $required_html = ( 'yes' === $atts['cats_required'] ) ? ' required' : '';
312
+ $required_mark_html = ( 'yes' === $atts['cats_required'] ) ? $required_mark_html_template : '';
313
+ $current_product_categories = ( 0 != $atts['product_id'] ) ? get_the_terms( $atts['product_id'], 'product_cat' ) : $args['cats'];
314
  $product_categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
315
  $product_categories_as_select_options = '';
316
  foreach ( $product_categories as $product_category ) {
317
  $selected = '';
318
  if ( ! empty( $current_product_categories ) ) {
319
  foreach ( $current_product_categories as $current_product_category ) {
320
+ if ( is_object( $current_product_category ) ) {
321
+ $current_product_category = $current_product_category->slug;
322
+ }
323
+ $selected .= selected( $current_product_category, $product_category->slug, false );
324
  }
325
  }
326
  $product_categories_as_select_options .= '<option value="' . $product_category->slug . '" ' . $selected . '>' . $product_category->name .'</option>';
327
  }
328
  $table_data[] = array(
329
+ '<label for="wcj_add_new_product_cats">' . __( 'Categories', 'woocommerce-jetpack' ) . $required_mark_html . '</label>',
330
+ '<select' . $required_html . ' multiple style="' . $input_style . '" id="wcj_add_new_product_cats" name="wcj_add_new_product_cats[]">' . $product_categories_as_select_options . '</select>'
331
  );
332
  }
333
  if ( 'yes' === $atts['tags_enabled'] ) {
334
  $required_html = ( 'yes' === $atts['tags_required'] ) ? ' required' : '';
335
+ $required_mark_html = ( 'yes' === $atts['tags_required'] ) ? $required_mark_html_template : '';
336
+ $current_product_tags = ( 0 != $atts['product_id'] ) ? get_the_terms( $atts['product_id'], 'product_tag' ) : $args['tags'];
337
  $products_tags = get_terms( 'product_tag', 'orderby=name&hide_empty=0' );
338
  $products_tags_as_select_options = '';
339
  foreach ( $products_tags as $products_tag ) {
340
  $selected = '';
341
  if ( ! empty( $current_product_tags ) ) {
342
  foreach ( $current_product_tags as $current_product_tag ) {
343
+ if ( is_object( $current_product_tag ) ) {
344
+ $current_product_tag = $current_product_tag->slug;
345
+ }
346
+ $selected .= selected( $current_product_tag, $products_tag->slug, false );
347
  }
348
  }
349
  $products_tags_as_select_options .= '<option value="' . $products_tag->slug . '" ' . $selected . '>' . $products_tag->name .'</option>';
350
  }
351
  $table_data[] = array(
352
+ '<label for="wcj_add_new_product_tags">' . __( 'Tags', 'woocommerce-jetpack' ) . $required_mark_html . '</label>',
353
+ '<select' . $required_html . ' multiple style="' . $input_style . '" id="wcj_add_new_product_tags" name="wcj_add_new_product_tags[]">' . $products_tags_as_select_options . '</select>'
354
  );
355
  }
356
 
includes/shortcodes/class-wcj-products-crowdfunding-shortcodes.php ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WooCommerce Jetpack Products Crowdfunding Shortcodes
4
+ *
5
+ * The WooCommerce Jetpack Products Crowdfunding Shortcodes class.
6
+ *
7
+ * @version 2.5.4
8
+ * @since 2.5.4
9
+ * @author Algoritmika Ltd.
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit;
13
+
14
+ if ( ! class_exists( 'WCJ_Products_Crowdfunding_Shortcodes' ) ) :
15
+
16
+ class WCJ_Products_Crowdfunding_Shortcodes extends WCJ_Shortcodes {
17
+
18
+ /**
19
+ * Constructor.
20
+ *
21
+ * @version 2.5.4
22
+ * @since 2.5.4
23
+ */
24
+ public function __construct() {
25
+
26
+ $this->the_shortcodes = array(
27
+ 'wcj_product_total_orders',
28
+ 'wcj_product_total_orders_items',
29
+ 'wcj_product_total_orders_sum',
30
+ 'wcj_product_crowdfunding_goal',
31
+ 'wcj_product_crowdfunding_goal_remaining',
32
+ 'wcj_product_crowdfunding_goal_remaining_progress_bar',
33
+ 'wcj_product_crowdfunding_startdate',
34
+ 'wcj_product_crowdfunding_deadline',
35
+ 'wcj_product_crowdfunding_time_remaining',
36
+ 'wcj_product_crowdfunding_time_remaining_progress_bar',
37
+ );
38
+
39
+ $this->the_atts = array(
40
+ 'product_id' => 0,
41
+ 'hide_currency' => 'no',
42
+ 'offset' => '',
43
+ );
44
+
45
+ parent::__construct();
46
+ }
47
+
48
+ /**
49
+ * Inits shortcode atts and properties.
50
+ *
51
+ * @version 2.5.4
52
+ * @since 2.5.4
53
+ * @param array $atts Shortcode atts.
54
+ * @return array The (modified) shortcode atts.
55
+ */
56
+ function init_atts( $atts ) {
57
+
58
+ // Atts
59
+ if ( 0 == $atts['product_id'] ) {
60
+ global $wcj_product_id_for_shortcode;
61
+ if ( 0 != $wcj_product_id_for_shortcode ) {
62
+ $atts['product_id'] = $wcj_product_id_for_shortcode;
63
+ } else {
64
+ $atts['product_id'] = get_the_ID();
65
+ }
66
+ if ( 0 == $atts['product_id'] ) return false;
67
+ }
68
+ $the_post_type = get_post_type( $atts['product_id'] );
69
+ if ( 'product' !== $the_post_type && 'product_variation' !== $the_post_type ) return false;
70
+
71
+ // Class properties
72
+ $this->the_product = wc_get_product( $atts['product_id'] );
73
+ if ( ! $this->the_product ) return false;
74
+
75
+ return $atts;
76
+ }
77
+
78
+ /**
79
+ * get_product_orders_data.
80
+ *
81
+ * @version 2.5.4
82
+ * @since 2.2.6
83
+ */
84
+ function get_product_orders_data( $return_value = 'total_orders', $atts ) {
85
+ global $woocommerce_loop, $post;
86
+ $saved_wc_loop = $woocommerce_loop;
87
+ $saved_post = $post;
88
+ $total_orders = 0;
89
+ $total_qty = 0;
90
+ $total_sum = 0;
91
+ $offset = 0;
92
+ $block_size = 96;
93
+ while( true ) {
94
+ $args = array(
95
+ 'post_type' => 'shop_order',
96
+ 'post_status' => 'wc-completed',
97
+ 'posts_per_page' => $block_size,
98
+ 'offset' => $offset,
99
+ 'orderby' => 'date',
100
+ 'order' => 'ASC',
101
+ 'date_query' => array(
102
+ array(
103
+ 'after' => get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_startdate', true ),
104
+ 'inclusive' => true,
105
+ ),
106
+ ),
107
+ );
108
+ $loop = new WP_Query( $args );
109
+ if ( ! $loop->have_posts() ) break;
110
+ while ( $loop->have_posts() ) : $loop->the_post();
111
+ $order_id = $loop->post->ID;
112
+ $the_order = wc_get_order( $order_id );
113
+ $the_items = $the_order->get_items();
114
+ $item_found = false;
115
+ foreach( $the_items as $item ) {
116
+ if ( $this->the_product->id == $item['product_id'] ) {
117
+ $total_sum += $item['line_total'] + $item['line_tax'];
118
+ $total_qty += $item['qty'];
119
+ $item_found = true;
120
+ }
121
+ }
122
+ if ( $item_found ) {
123
+ $total_orders++;
124
+ }
125
+ endwhile;
126
+ $offset += $block_size;
127
+ }
128
+ // wp_reset_postdata();
129
+ $woocommerce_loop = $saved_wc_loop;
130
+ $post = $saved_post;
131
+ setup_postdata( $post );
132
+ switch ( $return_value ) {
133
+ case 'orders_sum':
134
+ $return = $total_sum;
135
+ break;
136
+ case 'total_items':
137
+ $return = $total_qty;
138
+ break;
139
+ default: // 'total_orders'
140
+ $return = $total_orders;
141
+ break;
142
+ }
143
+ if ( 0 != $atts['offset'] ) {
144
+ $return += $atts['offset'];
145
+ }
146
+ return $return;
147
+ }
148
+
149
+ /**
150
+ * wcj_product_total_orders_items.
151
+ *
152
+ * @version 2.5.0
153
+ * @since 2.5.0
154
+ */
155
+ function wcj_product_total_orders_items( $atts ) {
156
+ return $this->get_product_orders_data( 'total_items', $atts );
157
+ }
158
+
159
+ /**
160
+ * wcj_product_total_orders.
161
+ *
162
+ * @version 2.5.0
163
+ * @since 2.2.6
164
+ */
165
+ function wcj_product_total_orders( $atts ) {
166
+ return $this->get_product_orders_data( 'total_orders', $atts );
167
+ }
168
+
169
+ /**
170
+ * wcj_product_total_orders_sum.
171
+ *
172
+ * @version 2.5.4
173
+ * @since 2.2.6
174
+ */
175
+ function wcj_product_total_orders_sum( $atts ) {
176
+ $total_orders_sum = $this->get_product_orders_data( 'orders_sum', $atts );
177
+ return ( 'yes' === $atts['hide_currency'] ) ? $total_orders_sum : wc_price( $total_orders_sum );
178
+ }
179
+
180
+ /**
181
+ * wcj_product_crowdfunding_startdate.
182
+ *
183
+ * @version 2.5.0
184
+ * @since 2.2.6
185
+ */
186
+ function wcj_product_crowdfunding_startdate( $atts ) {
187
+ return date_i18n( get_option( 'date_format' ), strtotime( get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_startdate', true ) ) );
188
+ }
189
+
190
+ /**
191
+ * wcj_product_crowdfunding_deadline.
192
+ *
193
+ * @version 2.5.0
194
+ * @since 2.2.6
195
+ */
196
+ function wcj_product_crowdfunding_deadline( $atts ) {
197
+ return date_i18n( get_option( 'date_format' ), strtotime( get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_deadline', true ) ) );
198
+ }
199
+
200
+ /**
201
+ * wcj_product_crowdfunding_time_remaining.
202
+ *
203
+ * @version 2.3.8
204
+ * @since 2.2.6
205
+ */
206
+ function wcj_product_crowdfunding_time_remaining( $atts ) {
207
+ $seconds_remaining = strtotime( $this->wcj_product_crowdfunding_deadline( $atts ) ) - current_time( 'timestamp' );
208
+ $days_remaining = floor( $seconds_remaining / ( 24 * 60 * 60 ) );
209
+ $hours_remaining = floor( $seconds_remaining / ( 60 * 60 ) );
210
+ $minutes_remaining = floor( $seconds_remaining / 60 );
211
+ if ( $seconds_remaining <= 0 ) return '';
212
+ if ( $days_remaining > 0 ) return ( 1 == $days_remaining ) ? $days_remaining . ' day left' : $days_remaining . ' days left';
213
+ if ( $hours_remaining > 0 ) return ( 1 == $hours_remaining ) ? $hours_remaining . ' hour left' : $hours_remaining . ' hours left';
214
+ if ( $minutes_remaining > 0 ) return ( 1 == $minutes_remaining ) ? $minutes_remaining . ' minute left' : $minutes_remaining . ' minutes left';
215
+ return ( 1 == $seconds_remaining ) ? $seconds_remaining . ' second left' : $seconds_remaining . ' seconds left';
216
+ /* if ( ( $seconds_remaining = strtotime( $this->wcj_product_crowdfunding_deadline( $atts ) ) - time() ) <= 0 ) return '';
217
+ if ( ( $days_remaining = floor( $seconds_remaining / ( 24 * 60 * 60 ) ) ) > 0 ) {
218
+ return ( 1 === $days_remaining ) ? $days_remaining . ' day left' : $days_remaining . ' days left';
219
+ }
220
+ if ( ( $hours_remaining = floor( $seconds_remaining / ( 60 * 60 ) ) ) > 0 ) {
221
+ return ( 1 === $hours_remaining ) ? $hours_remaining . ' hour left' : $hours_remaining . ' hours left';
222
+ }
223
+ if ( ( $minutes_remaining = floor( $seconds_remaining / 60 ) ) > 0 ) {
224
+ return ( 1 === $minutes_remaining ) ? $minutes_remaining . ' minute left' : $minutes_remaining . ' minutes left';
225
+ }
226
+ return ( 1 === $seconds_remaining ) ? $seconds_remaining . ' second left' : $seconds_remaining . ' seconds left'; */
227
+ }
228
+
229
+ /**
230
+ * wcj_product_crowdfunding_time_remaining_progress_bar.
231
+ *
232
+ * @version 2.5.4
233
+ * @since 2.5.0
234
+ */
235
+ function wcj_product_crowdfunding_time_remaining_progress_bar( $atts ) {
236
+ $deadline_seconds = strtotime( get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_deadline', true ) );
237
+ $startdate_seconds = strtotime( get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_startdate', true ) );
238
+
239
+ $seconds_remaining = $deadline_seconds - current_time( 'timestamp' );
240
+ $seconds_total = $deadline_seconds - $startdate_seconds;
241
+
242
+ $current_value = $seconds_remaining;
243
+ $max_value = $seconds_total;
244
+ return '<progress value="' . $current_value . '" max="' . $max_value . '"></progress>';
245
+ }
246
+
247
+ /**
248
+ * wcj_product_crowdfunding_goal.
249
+ *
250
+ * @version 2.5.4
251
+ * @since 2.2.6
252
+ */
253
+ function wcj_product_crowdfunding_goal( $atts ) {
254
+ $goal = get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_goal_sum', true );
255
+ return ( 'yes' === $atts['hide_currency'] ) ? $goal : wc_price( $goal );
256
+ }
257
+
258
+ /**
259
+ * wcj_product_crowdfunding_goal_remaining.
260
+ *
261
+ * @version 2.5.4
262
+ * @since 2.2.6
263
+ */
264
+ function wcj_product_crowdfunding_goal_remaining( $atts ) {
265
+ $goal = get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_goal_sum', true );
266
+ $total_orders_sum = $this->get_product_orders_data( 'orders_sum', $atts );
267
+ $goal_remaining = $goal - $total_orders_sum;
268
+ return ( 'yes' === $atts['hide_currency'] ) ? $goal_remaining : wc_price( $goal_remaining );
269
+ }
270
+
271
+ /**
272
+ * wcj_product_crowdfunding_goal_remaining_progress_bar.
273
+ *
274
+ * @version 2.5.4
275
+ * @since 2.5.0
276
+ */
277
+ function wcj_product_crowdfunding_goal_remaining_progress_bar( $atts ) {
278
+ $current_value = $this->get_product_orders_data( 'orders_sum', $atts );
279
+ $max_value = get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_goal_sum', true );
280
+ return '<progress value="' . $current_value . '" max="' . $max_value . '"></progress>';
281
+ }
282
+
283
+ }
284
+
285
+ endif;
286
+
287
+ return new WCJ_Products_Crowdfunding_Shortcodes();
includes/shortcodes/class-wcj-products-shortcodes.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Products Shortcodes class.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -17,14 +17,14 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.5.2
21
  */
22
  public function __construct() {
23
 
24
  $this->the_shortcodes = array(
25
  'wcj_product_image',
26
  'wcj_product_price',
27
- 'wcj_product_wholesale_price_table',
28
  'wcj_product_sku',
29
  'wcj_product_title',
30
  'wcj_product_weight',
@@ -33,18 +33,8 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
33
  'wcj_product_you_save',
34
  'wcj_product_you_save_percent',
35
  'wcj_product_tags',
36
- 'wcj_product_purchase_price',
37
  'wcj_product_total_sales',
38
- 'wcj_product_total_orders',
39
- 'wcj_product_total_orders_items',
40
- 'wcj_product_total_orders_sum',
41
- 'wcj_product_crowdfunding_goal',
42
- 'wcj_product_crowdfunding_goal_remaining',
43
- 'wcj_product_crowdfunding_goal_remaining_progress_bar',
44
- 'wcj_product_crowdfunding_startdate',
45
- 'wcj_product_crowdfunding_deadline',
46
- 'wcj_product_crowdfunding_time_remaining',
47
- 'wcj_product_crowdfunding_time_remaining_progress_bar',
48
  'wcj_product_shipping_class',
49
  'wcj_product_dimensions',
50
  'wcj_product_formatted_name',
@@ -83,6 +73,9 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
83
  'find' => '',
84
  'replace' => '',
85
  'offset' => '',
 
 
 
86
  );
87
 
88
  parent::__construct();
@@ -117,119 +110,59 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
117
  return $atts;
118
  }
119
 
120
- /**
121
- * get_product_orders_data.
122
- *
123
- * @version 2.5.0
124
- * @since 2.2.6
125
- */
126
- function get_product_orders_data( $return_value = 'total_orders', $atts ) {
127
- $total_orders = 0;
128
- $total_qty = 0;
129
- $total_sum = 0;
130
- $offset = 0;
131
- $block_size = 96;
132
- while( true ) {
133
- $args = array(
134
- 'post_type' => 'shop_order',
135
- 'post_status' => 'wc-completed',
136
- 'posts_per_page' => $block_size,
137
- 'offset' => $offset,
138
- 'orderby' => 'date',
139
- 'order' => 'ASC',
140
- 'date_query' => array(
141
- array(
142
- 'after' => get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_startdate', true ),
143
- 'inclusive' => true,
144
- ),
145
- ),
146
- );
147
- $loop = new WP_Query( $args );
148
- if ( ! $loop->have_posts() ) break;
149
- while ( $loop->have_posts() ) : $loop->the_post();
150
- $order_id = $loop->post->ID;
151
- $the_order = wc_get_order( $order_id );
152
- $the_items = $the_order->get_items();
153
- $item_found = false;
154
- foreach( $the_items as $item ) {
155
- if ( $this->the_product->id == $item['product_id'] ) {
156
- $total_sum += $item['line_total'] + $item['line_tax'];
157
- $total_qty += $item['qty'];
158
- $item_found = true;
159
- }
160
- }
161
- if ( $item_found ) {
162
- $total_orders++;
163
- }
164
- endwhile;
165
- $offset += $block_size;
166
- }
167
- wp_reset_postdata();
168
- switch ( $return_value ) {
169
- case 'orders_sum':
170
- $return = $total_sum;
171
- break;
172
- case 'total_items':
173
- $return = $total_qty;
174
- break;
175
- default: // 'total_orders'
176
- $return = $total_orders;
177
- break;
178
- }
179
- if ( 0 != $atts['offset'] ) {
180
- $return += $atts['offset'];
181
- }
182
- return $return;
183
- }
184
-
185
  /**
186
  * wcj_product_time_since_last_sale.
187
  *
188
- * @version 2.5.0
189
  * @since 2.4.0
190
- * @todo not finished
191
  */
192
  function wcj_product_time_since_last_sale( $atts ) {
193
- // Constants
194
- $days_to_cover = 90;
195
- $do_use_only_completed_orders = true;
196
- // Get the ID before new query
197
- $the_ID = get_the_ID();
198
  $offset = 0;
199
  $block_size = 96;
200
  while( true ) {
201
  // Create args for new query
202
  $args = array(
203
  'post_type' => 'shop_order',
204
- 'post_status' => ( true === $do_use_only_completed_orders ? 'wc-completed' : 'any' ),
205
  'posts_per_page' => $block_size,
206
  'offset' => $offset,
207
  'orderby' => 'date',
208
  'order' => 'DESC',
209
- 'date_query' => array( array( 'after' => strtotime( '-' . $days_to_cover . ' days' ) ) ),
210
  );
211
  // Run new query
212
  $loop = new WP_Query( $args );
213
- if ( ! $loop->have_posts() ) break;
 
 
214
  // Analyze the results, i.e. orders
215
  while ( $loop->have_posts() ) : $loop->the_post();
216
  $order = new WC_Order( $loop->post->ID );
217
  $items = $order->get_items();
218
  foreach ( $items as $item ) {
219
  // Run through all order's items
220
- if ( $item['product_id'] == $the_ID ) {
221
  // Found sale!
222
  $result = sprintf( __( '%s ago', 'woocommerce-jetpack' ), human_time_diff( get_the_time( 'U' ), current_time( 'timestamp' ) ) );
223
- wp_reset_postdata();
 
 
 
224
  return $result;
225
  }
226
  }
227
  endwhile;
228
  $offset += $block_size;
229
  }
230
- wp_reset_postdata();
 
 
 
231
  // No sales found
232
- return '';
233
  }
234
 
235
  /**
@@ -359,11 +292,16 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
359
  /**
360
  * wcj_product_list_attributes.
361
  *
362
- * @version 2.4.0
363
  * @since 2.4.0
364
  */
365
  function wcj_product_list_attributes( $atts ) {
366
- return ( $this->the_product->has_attributes() ) ? $this->the_product->list_attributes() : '';
 
 
 
 
 
367
  }
368
 
369
  /**
@@ -456,144 +394,19 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
456
  return '';
457
  }
458
 
459
- /**
460
- * wcj_product_total_orders_items.
461
- *
462
- * @version 2.5.0
463
- * @since 2.5.0
464
- */
465
- function wcj_product_total_orders_items( $atts ) {
466
- return $this->get_product_orders_data( 'total_items', $atts );
467
- }
468
-
469
- /**
470
- * wcj_product_total_orders.
471
- *
472
- * @version 2.5.0
473
- * @since 2.2.6
474
- */
475
- function wcj_product_total_orders( $atts ) {
476
- return $this->get_product_orders_data( 'total_orders', $atts );
477
- }
478
-
479
- /**
480
- * wcj_product_total_orders_sum.
481
- *
482
- * @version 2.5.0
483
- * @since 2.2.6
484
- */
485
- function wcj_product_total_orders_sum( $atts ) {
486
- return $this->get_product_orders_data( 'orders_sum', $atts );
487
- }
488
-
489
- /**
490
- * wcj_product_crowdfunding_startdate.
491
- *
492
- * @version 2.5.0
493
- * @since 2.2.6
494
- */
495
- function wcj_product_crowdfunding_startdate( $atts ) {
496
- return date_i18n( get_option( 'date_format' ), strtotime( get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_startdate', true ) ) );
497
- }
498
-
499
- /**
500
- * wcj_product_crowdfunding_deadline.
501
- *
502
- * @version 2.5.0
503
- * @since 2.2.6
504
- */
505
- function wcj_product_crowdfunding_deadline( $atts ) {
506
- return date_i18n( get_option( 'date_format' ), strtotime( get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_deadline', true ) ) );
507
- }
508
-
509
- /**
510
- * wcj_product_crowdfunding_time_remaining.
511
- *
512
- * @version 2.3.8
513
- * @since 2.2.6
514
- */
515
- function wcj_product_crowdfunding_time_remaining( $atts ) {
516
- $seconds_remaining = strtotime( $this->wcj_product_crowdfunding_deadline( $atts ) ) - current_time( 'timestamp' );
517
- $days_remaining = floor( $seconds_remaining / ( 24 * 60 * 60 ) );
518
- $hours_remaining = floor( $seconds_remaining / ( 60 * 60 ) );
519
- $minutes_remaining = floor( $seconds_remaining / 60 );
520
- if ( $seconds_remaining <= 0 ) return '';
521
- if ( $days_remaining > 0 ) return ( 1 == $days_remaining ) ? $days_remaining . ' day left' : $days_remaining . ' days left';
522
- if ( $hours_remaining > 0 ) return ( 1 == $hours_remaining ) ? $hours_remaining . ' hour left' : $hours_remaining . ' hours left';
523
- if ( $minutes_remaining > 0 ) return ( 1 == $minutes_remaining ) ? $minutes_remaining . ' minute left' : $minutes_remaining . ' minutes left';
524
- return ( 1 == $seconds_remaining ) ? $seconds_remaining . ' second left' : $seconds_remaining . ' seconds left';
525
- /* if ( ( $seconds_remaining = strtotime( $this->wcj_product_crowdfunding_deadline( $atts ) ) - time() ) <= 0 ) return '';
526
- if ( ( $days_remaining = floor( $seconds_remaining / ( 24 * 60 * 60 ) ) ) > 0 ) {
527
- return ( 1 === $days_remaining ) ? $days_remaining . ' day left' : $days_remaining . ' days left';
528
- }
529
- if ( ( $hours_remaining = floor( $seconds_remaining / ( 60 * 60 ) ) ) > 0 ) {
530
- return ( 1 === $hours_remaining ) ? $hours_remaining . ' hour left' : $hours_remaining . ' hours left';
531
- }
532
- if ( ( $minutes_remaining = floor( $seconds_remaining / 60 ) ) > 0 ) {
533
- return ( 1 === $minutes_remaining ) ? $minutes_remaining . ' minute left' : $minutes_remaining . ' minutes left';
534
- }
535
- return ( 1 === $seconds_remaining ) ? $seconds_remaining . ' second left' : $seconds_remaining . ' seconds left'; */
536
- }
537
-
538
- /**
539
- * wcj_product_crowdfunding_time_remaining_progress_bar.
540
- *
541
- * @version 2.5.0
542
- * @since 2.5.0
543
- */
544
- function wcj_product_crowdfunding_time_remaining_progress_bar( $atts ) {
545
- $deadline_seconds = strtotime( get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_deadline', true ) );
546
- $startdate_seconds = strtotime( get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_startdate', true ) );
547
-
548
- $seconds_remaining = $deadline_seconds - current_time( 'timestamp' );
549
- $seconds_total = $deadline_seconds - $startdate_seconds;
550
-
551
- $current_value = $seconds_remaining;
552
- $max_value = $seconds_total;
553
- $return = '<progress value="' . $current_value . '" max="' . $max_value . '"></progress>';
554
- }
555
-
556
- /**
557
- * wcj_product_crowdfunding_goal.
558
- *
559
- * @version 2.2.6
560
- * @since 2.2.6
561
- */
562
- function wcj_product_crowdfunding_goal( $atts ) {
563
- return get_post_meta( $this->the_product->id, '_' . 'wcj_crowdfunding_goal_sum', true );
564
- }
565
-
566
- /**
567
- * wcj_product_crowdfunding_goal_remaining.
568
- *
569
- * @version 2.2.6
570
- * @since 2.2.6
571
- */
572
- function wcj_product_crowdfunding_goal_remaining( $atts ) {
573
- return $this->wcj_product_crowdfunding_goal( $atts ) - $this->wcj_product_total_orders_sum( $atts );
574
- }
575
-
576
- /**
577
- * wcj_product_crowdfunding_goal_remaining_progress_bar.
578
- *
579
- * @version 2.5.0
580
- * @since 2.5.0
581
- */
582
- function wcj_product_crowdfunding_goal_remaining_progress_bar( $atts ) {
583
- $current_value = $this->wcj_product_total_orders_sum( $atts );
584
- $max_value = $this->wcj_product_crowdfunding_goal( $atts );
585
- return '<progress value="' . $current_value . '" max="' . $max_value . '"></progress>';
586
- }
587
-
588
  /**
589
  * wcj_product_total_sales.
590
  *
591
- * @version 2.4.0
592
  * @since 2.2.6
593
  */
594
  function wcj_product_total_sales( $atts ) {
595
  $product_custom_fields = get_post_custom( $this->the_product->id );
596
- return ( isset( $product_custom_fields['total_sales'][0] ) ) ? $product_custom_fields['total_sales'][0] : '';
 
 
 
 
597
  }
598
 
599
  /**
4
  *
5
  * The WooCommerce Jetpack Products Shortcodes class.
6
  *
7
+ * @version 2.5.4
8
  * @author Algoritmika Ltd.
9
  */
10
 
17
  /**
18
  * Constructor.
19
  *
20
+ * @version 2.5.4
21
  */
22
  public function __construct() {
23
 
24
  $this->the_shortcodes = array(
25
  'wcj_product_image',
26
  'wcj_product_price',
27
+ 'wcj_product_wholesale_price_table', // WooCommerce Wholesale Price
28
  'wcj_product_sku',
29
  'wcj_product_title',
30
  'wcj_product_weight',
33
  'wcj_product_you_save',
34
  'wcj_product_you_save_percent',
35
  'wcj_product_tags',
36
+ 'wcj_product_purchase_price', // WooCommerce Product Cost Price
37
  'wcj_product_total_sales',
 
 
 
 
 
 
 
 
 
 
38
  'wcj_product_shipping_class',
39
  'wcj_product_dimensions',
40
  'wcj_product_formatted_name',
73
  'find' => '',
74
  'replace' => '',
75
  'offset' => '',
76
+ 'days_to_cover' => 90,
77
+ 'order_status' => 'wc-completed',
78
+ 'hide_if_no_sales' => 'no',
79
  );
80
 
81
  parent::__construct();
110
  return $atts;
111
  }
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  /**
114
  * wcj_product_time_since_last_sale.
115
  *
116
+ * @version 2.5.4
117
  * @since 2.4.0
 
118
  */
119
  function wcj_product_time_since_last_sale( $atts ) {
120
+ global $woocommerce_loop, $post;
121
+ $saved_wc_loop = $woocommerce_loop;
122
+ $saved_post = $post;
 
 
123
  $offset = 0;
124
  $block_size = 96;
125
  while( true ) {
126
  // Create args for new query
127
  $args = array(
128
  'post_type' => 'shop_order',
129
+ 'post_status' => $atts['order_status'],
130
  'posts_per_page' => $block_size,
131
  'offset' => $offset,
132
  'orderby' => 'date',
133
  'order' => 'DESC',
134
+ 'date_query' => array( array( 'after' => strtotime( '-' . $atts['days_to_cover'] . ' days' ) ) ),
135
  );
136
  // Run new query
137
  $loop = new WP_Query( $args );
138
+ if ( ! $loop->have_posts() ) {
139
+ break;
140
+ }
141
  // Analyze the results, i.e. orders
142
  while ( $loop->have_posts() ) : $loop->the_post();
143
  $order = new WC_Order( $loop->post->ID );
144
  $items = $order->get_items();
145
  foreach ( $items as $item ) {
146
  // Run through all order's items
147
+ if ( $item['product_id'] == $atts['product_id'] ) {
148
  // Found sale!
149
  $result = sprintf( __( '%s ago', 'woocommerce-jetpack' ), human_time_diff( get_the_time( 'U' ), current_time( 'timestamp' ) ) );
150
+ // wp_reset_postdata();
151
+ $woocommerce_loop = $saved_wc_loop;
152
+ $post = $saved_post;
153
+ setup_postdata( $post );
154
  return $result;
155
  }
156
  }
157
  endwhile;
158
  $offset += $block_size;
159
  }
160
+ // wp_reset_postdata();
161
+ $woocommerce_loop = $saved_wc_loop;
162
+ $post = $saved_post;
163
+ setup_postdata( $post );
164
  // No sales found
165
+ return ( 'yes' === $atts['hide_if_no_sales'] ? '' : __( 'No sales yet.', 'woocommerce-jetpack' ) );
166
  }
167
 
168
  /**
292
  /**
293
  * wcj_product_list_attributes.
294
  *
295
+ * @version 2.5.4
296
  * @since 2.4.0
297
  */
298
  function wcj_product_list_attributes( $atts ) {
299
+ if ( $this->the_product->has_attributes() ) {
300
+ ob_start();
301
+ $this->the_product->list_attributes();
302
+ return ob_get_clean();
303
+ }
304
+ return '';
305
  }
306
 
307
  /**
394
  return '';
395
  }
396
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
  /**
398
  * wcj_product_total_sales.
399
  *
400
+ * @version 2.5.4
401
  * @since 2.2.6
402
  */
403
  function wcj_product_total_sales( $atts ) {
404
  $product_custom_fields = get_post_custom( $this->the_product->id );
405
+ $total_sales = ( isset( $product_custom_fields['total_sales'][0] ) ) ? $product_custom_fields['total_sales'][0] : '';
406
+ if ( 0 != $atts['offset'] ) {
407
+ $total_sales += $atts['offset'];
408
+ }
409
+ return ( 0 == $total_sales && 'yes' === $atts['hide_if_zero'] ) ? '' : $total_sales;
410
  }
411
 
412
  /**
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === Booster for WooCommerce ===
2
- Contributors: algoritmika,anbinder
3
- Tags: woocommerce,booster for woocommerce,woocommerce jetpack,custom price labels,call for price,currency symbol,remove sorting,remove old product slugs,add to cart text,order number,sequential order numbering,email pdf invoice,pdf invoice,pdf invoices,already in cart,empty cart,redirect to checkout,minimum order amount,customize checkout fields,checkout fields,email,customize product tabs,product tabs,related products number,empty cart,redirect add to cart,redirect to checkout,product already in cart,custom payment gateway,payment gateway icon,auto-complete all orders,custom order statuses,custom order status,remove text from price,custom css,hide categories count,hide subcategories count,hide category count,hide subcategory count,display total sales,custom product tabs,remove product tab,payment gateway fee,vat,gateway by country,price by country,currency switcher
4
  Requires at least: 4.1
5
  Tested up to: 4.5
6
- Stable tag: 2.5.3
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -95,8 +95,9 @@ Booster for WooCommerce is a WordPress plugin that supercharges your site with a
95
  * *Admin Tools* - Booster for WooCommerce debug and log tools.
96
  * *Booster WPML* - Booster for WooCommerce basic WPML support.
97
  * *EU VAT Number* - Collect and validate EU VAT numbers on WooCommerce checkout. Automatically disable VAT for valid numbers. Add all EU countries VAT standard rates to WooCommerce.
 
98
  * *Emails* - Add custom emails. Add another email recipient(s) to all WooCommerce emails.
99
- * *General* - Separate custom CSS for front and back end. Shortcodes in Wordpress text widgets. Export tools. Custom roles tool.
100
  * *Old Slugs* - Remove old WooCommerce products slugs.
101
  * *Reports* - WooCommerce stock, sales, customers etc. reports.
102
 
@@ -126,12 +127,40 @@ To unlock all Booster for WooCommerce features, please install additional [Boost
126
 
127
  == Changelog ==
128
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  = 2.5.3 - 04/07/2016 =
130
  * Dev - Shortcodes - Orders - `[wcj_order_total_refunded]` shortcode added.
131
  * Dev - Shortcodes - Orders - `[wcj_order_taxes_html]` shortcode added.
132
  * Dev - Shortcodes - Orders - `[wcj_order_items_meta]` shortcode added.
133
  * Dev - PRICES & CURRENCIES - Currency Exchange Rates - "Logging" option removed.
134
- * Fix - PRICES & CURRENCIES - Prices and Currencies by Country - Price Filter widget fixed. `add_hooks()` function moved from `init` hook to constructor.
135
  * Dev - PRICES & CURRENCIES - Price by User Role - Class functions replaced with global functions.
136
  * Dev - PRODUCTS - Bookings - "Hide Quantity Selector" option added.
137
  * Dev - PRODUCTS - Product Add to Cart - "Open External Products on Add to Cart in New Window" option added.
@@ -200,7 +229,7 @@ To unlock all Booster for WooCommerce features, please install additional [Boost
200
  * Fix - PDF INVOICING & PACKING SLIPS - Report Tool - Querying by document date instead of order date.
201
  * Dev - EMAILS & MISC. - General - "PayPal Email per Product" option added.
202
  * Dev - EMAILS & MISC. - EU VAT Number - Option ("Display") to append EU VAT number to order and my account billing addresses added.
203
- * Fix - EMAILS & MISC. - EU VAT Number - `woocommerce_matched_rates` filter changed to `woocommerce_find_rates` - this fixes the issue with sipping tax not exempting.
204
  * Tweak - "Unlock all" link modified.
205
  * Tweak - "No active modules found." message added.
206
  * Tweak - PRODUCTS - Product Images - Module settings rearranged.
1
  === Booster for WooCommerce ===
2
+ Contributors: algoritmika
3
+ Tags: woocommerce,booster for woocommerce,woocommerce jetpack
4
  Requires at least: 4.1
5
  Tested up to: 4.5
6
+ Stable tag: 2.5.4
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
95
  * *Admin Tools* - Booster for WooCommerce debug and log tools.
96
  * *Booster WPML* - Booster for WooCommerce basic WPML support.
97
  * *EU VAT Number* - Collect and validate EU VAT numbers on WooCommerce checkout. Automatically disable VAT for valid numbers. Add all EU countries VAT standard rates to WooCommerce.
98
+ * *Export* - WooCommerce export tools.
99
  * *Emails* - Add custom emails. Add another email recipient(s) to all WooCommerce emails.
100
+ * *General* - Separate custom CSS for front and back end. Shortcodes in Wordpress text widgets. Custom roles tool.
101
  * *Old Slugs* - Remove old WooCommerce products slugs.
102
  * *Reports* - WooCommerce stock, sales, customers etc. reports.
103
 
127
 
128
  == Changelog ==
129
 
130
+ = 2.5.4 - 19/07/2016 =
131
+ * Fix - Manage Settings - Import - New line issue fixed.
132
+ * Dev - Shortcodes - General - `[wcj_country_select_drop_down_list]` - `replace_with_currency` attribute added.
133
+ * Dev - Shortcodes - Orders - `[wcj_order_tax_by_class]` shortcode added.
134
+ * Dev - Shortcodes - Orders - `[wcj_order_total_by_tax_class]` shortcode added.
135
+ * Dev - Shortcodes - Orders - `[wcj_order_subtotal_by_tax_class]` shortcode added.
136
+ * Fix - Shortcodes - Products - Crowdfunding - `get_product_orders_data()` - WooCommerce loop fixed.
137
+ * Fix - Shortcodes - Products - `[wcj_product_time_since_last_sale]` WooCommerce loop fixed.
138
+ * Fix - Shortcodes - Products - `[wcj_product_crowdfunding_time_remaining_progress_bar]` fixed.
139
+ * Fix - Shortcodes - Products - `[wcj_product_crowdfunding_goal]`, `[wcj_product_crowdfunding_goal_remaining]`, `[wcj_product_total_orders_sum]` fixed (and `hide_currency` attribute added).
140
+ * Fix - Shortcodes - Products - `[wcj_product_list_attributes]` fixed.
141
+ * Dev - Shortcodes - Products - `[wcj_product_total_sales]` - `hide_if_zero` and `offset` attributes added.
142
+ * Dev - Shortcodes - Products - `[wcj_product_time_since_last_sale]` attributes added.
143
+ * Dev - Shortcodes - Products - Crowdfunding - Code refactoring - moved to separate file.
144
+ * Fix - PRICES & CURRENCIES - Prices and Currencies by Country - Getting `customer_country_group_id` on every `get_customer_country_group_id()` function call.
145
+ * Dev - PRICES & CURRENCIES - Prices and Currencies by Country - `add_hooks()` function moved from `init` hook to constructor.
146
+ * Dev - PRICES & CURRENCIES - Prices and Currencies by Country - "Add Flags Images to Select Drop-Down Box" option added (`[wcj_country_select_drop_down_list]` shortcode).
147
+ * Dev - PRICES & CURRENCIES - Wholesale Price - "Products to exclude" option added.
148
+ * Dev - PRODUCTS - Product by User - Messages options added.
149
+ * Dev - PRODUCTS - Product by User - Fields ids; `label` tags added.
150
+ * Dev - PRODUCTS - Product by User - Fields (all except Image field) refilled when validate returns false and after product successfully added.
151
+ * Dev - PRODUCTS - Product by User - "Require Unique Title" option added.
152
+ * Fix - EMAILS & MISC. - EU VAT Number - Started using WooCommerce customer `set_is_vat_exempt()` function.
153
+ * Fix - EMAILS & MISC. - EU VAT Number - AJAX call fixed.
154
+ * Dev - EMAILS & MISC. - Export - Initial module release (all tools moved from General module).
155
+ * Dev - EMAILS & MISC. - General - Export Orders tool - Order number, status, item count, total, payment method, billing and shipping info columns added.
156
+ * Tweak - Tags in plugin description and contributors changed.
157
+
158
  = 2.5.3 - 04/07/2016 =
159
  * Dev - Shortcodes - Orders - `[wcj_order_total_refunded]` shortcode added.
160
  * Dev - Shortcodes - Orders - `[wcj_order_taxes_html]` shortcode added.
161
  * Dev - Shortcodes - Orders - `[wcj_order_items_meta]` shortcode added.
162
  * Dev - PRICES & CURRENCIES - Currency Exchange Rates - "Logging" option removed.
163
+ * Fix - PRICES & CURRENCIES - Prices and Currencies by Country - Price Filter widget fixed. `woocommerce_currency_symbol` hook moved from `init` hook to constructor.
164
  * Dev - PRICES & CURRENCIES - Price by User Role - Class functions replaced with global functions.
165
  * Dev - PRODUCTS - Bookings - "Hide Quantity Selector" option added.
166
  * Dev - PRODUCTS - Product Add to Cart - "Open External Products on Add to Cart in New Window" option added.
229
  * Fix - PDF INVOICING & PACKING SLIPS - Report Tool - Querying by document date instead of order date.
230
  * Dev - EMAILS & MISC. - General - "PayPal Email per Product" option added.
231
  * Dev - EMAILS & MISC. - EU VAT Number - Option ("Display") to append EU VAT number to order and my account billing addresses added.
232
+ * Fix - EMAILS & MISC. - EU VAT Number - `woocommerce_matched_rates` filter changed to `woocommerce_find_rates` - this fixes the issue with shipping tax not exempting.
233
  * Tweak - "Unlock all" link modified.
234
  * Tweak - "No active modules found." message added.
235
  * Tweak - PRODUCTS - Product Images - Module settings rearranged.
woocommerce-jetpack.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: http://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
- Version: 2.5.3
7
  Author: Algoritmika Ltd
8
  Author URI: http://www.algoritmika.com
9
  Text Domain: woocommerce-jetpack
@@ -28,7 +28,7 @@ if ( ! class_exists( 'WC_Jetpack' ) ) :
28
  * Main WC_Jetpack Class
29
  *
30
  * @class WC_Jetpack
31
- * @version 2.5.3
32
  */
33
 
34
  final class WC_Jetpack {
@@ -39,7 +39,7 @@ final class WC_Jetpack {
39
  * @var string
40
  * @since 2.4.7
41
  */
42
- public $version = '2.5.3';
43
 
44
  /**
45
  * @var WC_Jetpack The single instance of the class
@@ -462,10 +462,9 @@ final class WC_Jetpack {
462
  /**
463
  * include_shortcodes.
464
  *
465
- * @version 2.5.2
466
  */
467
  private function include_shortcodes() {
468
- //if ( 'yes' === get_option( 'wcj_shortcodes_enabled', 'no' ) ) {
469
  if ( ! wcj_is_module_enabled( 'general' ) || ( wcj_is_module_enabled( 'general' ) && 'no' === get_option( 'wcj_general_shortcodes_disable_booster_shortcodes', 'no' ) ) ) {
470
  include_once( 'includes/shortcodes/class-wcj-shortcodes.php' );
471
  include_once( 'includes/shortcodes/class-wcj-general-shortcodes.php' );
@@ -473,6 +472,7 @@ final class WC_Jetpack {
473
  include_once( 'includes/shortcodes/class-wcj-orders-shortcodes.php' );
474
  include_once( 'includes/shortcodes/class-wcj-order-items-shortcodes.php' );
475
  include_once( 'includes/shortcodes/class-wcj-products-shortcodes.php' );
 
476
  include_once( 'includes/shortcodes/class-wcj-products-add-form-shortcodes.php' );
477
  include_once( 'includes/shortcodes/class-wcj-input-field-shortcodes.php' );
478
  }
@@ -481,7 +481,7 @@ final class WC_Jetpack {
481
  /**
482
  * Include modules and submodules
483
  *
484
- * @version 2.5.3
485
  */
486
  function include_modules() {
487
  $modules_files = array(
@@ -543,6 +543,7 @@ final class WC_Jetpack {
543
  'includes/class-wcj-currency-exchange-rates.php',
544
  'includes/class-wcj-price-formats.php',
545
  'includes/class-wcj-general.php',
 
546
  // 'includes/class-wcj-shortcodes-module.php',
547
  'includes/class-wcj-eu-vat-number.php',
548
  'includes/class-wcj-old-slugs.php',
@@ -629,7 +630,7 @@ final class WC_Jetpack {
629
  /**
630
  * manage_options_import.
631
  *
632
- * @version 2.5.2
633
  * @since 2.5.2
634
  */
635
  function manage_options_import() {
@@ -641,7 +642,7 @@ final class WC_Jetpack {
641
  } else {
642
  $import_counter = 0;
643
  $import_settings = file_get_contents( $_FILES['booster_import_settings_file']['tmp_name'] );
644
- $import_settings = explode( PHP_EOL, $import_settings );
645
  if ( ! is_array( $import_settings ) || 2 !== count( $import_settings ) ) {
646
  $wcj_notice .= __( 'Wrong file format!', 'woocommerce-jetpack' );
647
  } else {
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: http://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
+ Version: 2.5.4
7
  Author: Algoritmika Ltd
8
  Author URI: http://www.algoritmika.com
9
  Text Domain: woocommerce-jetpack
28
  * Main WC_Jetpack Class
29
  *
30
  * @class WC_Jetpack
31
+ * @version 2.5.4
32
  */
33
 
34
  final class WC_Jetpack {
39
  * @var string
40
  * @since 2.4.7
41
  */
42
+ public $version = '2.5.4';
43
 
44
  /**
45
  * @var WC_Jetpack The single instance of the class
462
  /**
463
  * include_shortcodes.
464
  *
465
+ * @version 2.5.4
466
  */
467
  private function include_shortcodes() {
 
468
  if ( ! wcj_is_module_enabled( 'general' ) || ( wcj_is_module_enabled( 'general' ) && 'no' === get_option( 'wcj_general_shortcodes_disable_booster_shortcodes', 'no' ) ) ) {
469
  include_once( 'includes/shortcodes/class-wcj-shortcodes.php' );
470
  include_once( 'includes/shortcodes/class-wcj-general-shortcodes.php' );
472
  include_once( 'includes/shortcodes/class-wcj-orders-shortcodes.php' );
473
  include_once( 'includes/shortcodes/class-wcj-order-items-shortcodes.php' );
474
  include_once( 'includes/shortcodes/class-wcj-products-shortcodes.php' );
475
+ include_once( 'includes/shortcodes/class-wcj-products-crowdfunding-shortcodes.php' );
476
  include_once( 'includes/shortcodes/class-wcj-products-add-form-shortcodes.php' );
477
  include_once( 'includes/shortcodes/class-wcj-input-field-shortcodes.php' );
478
  }
481
  /**
482
  * Include modules and submodules
483
  *
484
+ * @version 2.5.4
485
  */
486
  function include_modules() {
487
  $modules_files = array(
543
  'includes/class-wcj-currency-exchange-rates.php',
544
  'includes/class-wcj-price-formats.php',
545
  'includes/class-wcj-general.php',
546
+ 'includes/class-wcj-export-import.php',
547
  // 'includes/class-wcj-shortcodes-module.php',
548
  'includes/class-wcj-eu-vat-number.php',
549
  'includes/class-wcj-old-slugs.php',
630
  /**
631
  * manage_options_import.
632
  *
633
+ * @version 2.5.4
634
  * @since 2.5.2
635
  */
636
  function manage_options_import() {
642
  } else {
643
  $import_counter = 0;
644
  $import_settings = file_get_contents( $_FILES['booster_import_settings_file']['tmp_name'] );
645
+ $import_settings = explode( PHP_EOL, preg_replace( '~(*BSR_ANYCRLF)\R~', PHP_EOL, $import_settings ) );
646
  if ( ! is_array( $import_settings ) || 2 !== count( $import_settings ) ) {
647
  $wcj_notice .= __( 'Wrong file format!', 'woocommerce-jetpack' );
648
  } else {