Booster for WooCommerce - Version 3.2.2

Version Description

  • 12/11/2017 =
  • Dev - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - "Advanced: Price Filters Priority" option added.
  • Dev - PRICES & CURRENCIES - Price by User Role - "Advanced: Price Filters Priority" option added.
  • Dev - PRODUCTS - Product Addons - "Text" addon type added.
  • Dev - CART & CHECKOUT - Checkout Custom Fields - Template options added. Now (by default) using styling in emails and order received page.
  • Dev - CART & CHECKOUT - EU VAT Number - Advanced Options - "Skip VAT Validation for Selected Countries" option added.
  • Dev - CART & CHECKOUT - EU VAT Number - Display - After order table - Output restyled.
  • Dev - CART & CHECKOUT - EU VAT Number - Admin settings descriptions and styling updated.
  • Dev - PAYMENT GATEWAYS - Gateways by User Role - Module's main hook priority lowered (so e.g. it's now run before the "Gateways Min/Max Amounts" module).
  • Fix - SHIPPING & ORDERS - Order Custom Statuses - Custom Statuses Tool - Adding "Delete" and "Edit" buttons to Booster's custom statuses only.
  • Dev - SHIPPING & ORDERS - Order Custom Statuses - Custom Statuses Tool - "Delete All Custom Statuses" button added.
  • Dev - SHIPPING & ORDERS - Order Custom Statuses - Custom Statuses Tool - Sanitizing slug when adding new custom status.
  • Dev - SHIPPING & ORDERS - Order Custom Statuses - Default Order Status - "No changes" option added.
  • Dev - SHIPPING & ORDERS - Order Custom Statuses - Major code refactoring and cleanup.
  • Dev - SHIPPING & ORDERS - Order Min/Max Quantities - Min and max quantities added to quantity input on single product page (if "Per Item Quantity" is enabled).
  • Dev - SHIPPING & ORDERS - Order Min/Max Quantities - "Per Item Quantity on Per Product Basis" added.
  • Dev - PDF INVOICING & PACKING SLIPS - Invoices Renumerate Tool - Code cleanup. Restyling.
  • Dev - PDF INVOICING & PACKING SLIPS - Numbering - "Template" option added.
  • Dev - PDF INVOICING & PACKING SLIPS - Styling - Admin settings - Minor restyling.
  • Dev - EMAILS & MISC. - Breadcrumbs - hide_breadcrumbs_with_css() - Additional identifier added.
  • Dev - EMAILS & MISC. - Custom Emails - WooCommerce v3.x.x compatibility - post_status.
  • Dev - Shortcodes - Orders - [wcj_order_items_table] - wcj_order_items_table_data filter added.
  • Dev - Shortcodes - Orders - [wcj_order_items_table] - sort_by_column attribute added.
  • Dev - Functions - Exchange Rates - Deprecated average exchange rates (Yahoo) calculation removed.
  • Dev - Functions - Exchange Rates - Average exchange rates (Fixer.io) calculation added.
  • Dev - Functions - Exchange Rates - Exchange Rates Server - "Fixer.io" server added.
  • Dev - Functions - Exchange Rates - Exchange Rates Server - "Yahoo" URL updated.
  • Dev - Functions - Orders - Cleanup (wcj_get_order_statuses()).
  • Dev - Functions - Price and Currency - wc_get_product_purchase_price() - Converting post meta to int before adding (fixes PHP 7 notice).
  • Fix - Functions - Users - wcj_get_current_user_first_role() - Code changed, so now user role is always correctly identified (i.e. with any array index).
  • Dev - WCJ_Invoice - Default values added to get_option() calls.
  • Dev - WCJ_Product - Class removed (get_purchase_price() function moved to wc_get_product_purchase_price()).
Download this release

Release Info

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

Code changes from version 3.2.1 to 3.2.2

Files changed (44) hide show
  1. includes/class-wcj-breadcrumbs.php +4 -2
  2. includes/class-wcj-checkout-custom-fields.php +79 -69
  3. includes/class-wcj-currency-exchange-rates.php +1 -0
  4. includes/class-wcj-emails.php +1 -1
  5. includes/class-wcj-eu-vat-number.php +3 -3
  6. includes/class-wcj-multicurrency.php +9 -5
  7. includes/class-wcj-my-account.php +1 -1
  8. includes/class-wcj-order-custom-statuses.php +85 -248
  9. includes/class-wcj-order-quantities.php +141 -5
  10. includes/class-wcj-payment-gateways-by-user-role.php +3 -3
  11. includes/class-wcj-price-by-user-role.php +8 -7
  12. includes/class-wcj-product-addons.php +21 -7
  13. includes/classes/class-wcj-invoice.php +27 -41
  14. includes/classes/class-wcj-product.php +0 -58
  15. includes/emails/class-wc-email-wcj-custom.php +4 -4
  16. includes/exchange-rates/class-wcj-exchange-rates.php +30 -3
  17. includes/functions/wcj-functions-eu-vat.php +10 -3
  18. includes/functions/wcj-functions-exchange-rates.php +81 -70
  19. includes/functions/wcj-functions-orders.php +20 -32
  20. includes/functions/wcj-functions-price-currency.php +45 -3
  21. includes/functions/wcj-functions-products.php +1 -14
  22. includes/functions/wcj-functions-users.php +4 -3
  23. includes/js/wcj-ajax-exchange-rates-average.js +33 -0
  24. includes/js/wcj-order-quantities.js +26 -0
  25. includes/js/wcj-product-addons.js +5 -1
  26. includes/pdf-invoices/class-wcj-pdf-invoicing-renumerate-tool.php +34 -22
  27. includes/reports/wcj-class-reports-monthly-sales.php +12 -5
  28. includes/settings/meta-box/wcj-settings-meta-box-order-quantities.php +61 -0
  29. includes/settings/meta-box/wcj-settings-meta-box-product-addons.php +2 -1
  30. includes/settings/wcj-settings-checkout-custom-fields.php +40 -2
  31. includes/settings/wcj-settings-eu-vat-number.php +34 -17
  32. includes/settings/wcj-settings-multicurrency.php +8 -1
  33. includes/settings/wcj-settings-my-account.php +1 -1
  34. includes/settings/wcj-settings-order-custom-statuses.php +3 -3
  35. includes/settings/wcj-settings-order-quantities.php +26 -8
  36. includes/settings/wcj-settings-pdf-invoicing-numbering.php +10 -5
  37. includes/settings/wcj-settings-pdf-invoicing-styling.php +2 -2
  38. includes/settings/wcj-settings-pdf-invoicing.php +2 -2
  39. includes/settings/wcj-settings-price-by-user-role.php +8 -1
  40. includes/settings/wcj-settings-product-addons.php +2 -1
  41. includes/shortcodes/class-wcj-order-items-shortcodes.php +34 -3
  42. includes/tools/class-wcj-order-statuses-tool.php +284 -0
  43. readme.txt +34 -1
  44. woocommerce-jetpack.php +4 -5
includes/class-wcj-breadcrumbs.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Breadcrumbs
4
  *
5
- * @version 2.9.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -57,8 +57,9 @@ class WCJ_Breadcrumbs extends WCJ_Module {
57
  /**
58
  * hide_breadcrumbs_with_css.
59
  *
60
- * @version 2.9.0
61
  * @since 2.9.0
 
62
  * @todo (maybe) add more identifiers
63
  */
64
  function hide_breadcrumbs_with_css() {
@@ -68,6 +69,7 @@ class WCJ_Breadcrumbs extends WCJ_Module {
68
  '.breadcrumbs',
69
  '.breadcrumb',
70
  '#breadcrumbs',
 
71
  );
72
  echo '<style>' . implode( ', ', $identifiers ) . ' { display: none !important; }' . '</style>';
73
  }
2
  /**
3
  * Booster for WooCommerce - Module - Breadcrumbs
4
  *
5
+ * @version 3.2.2
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
57
  /**
58
  * hide_breadcrumbs_with_css.
59
  *
60
+ * @version 3.2.2
61
  * @since 2.9.0
62
+ * @todo (maybe) option to add custom identifiers
63
  * @todo (maybe) add more identifiers
64
  */
65
  function hide_breadcrumbs_with_css() {
69
  '.breadcrumbs',
70
  '.breadcrumb',
71
  '#breadcrumbs',
72
+ '.breadcrumbs-wrapper',
73
  );
74
  echo '<style>' . implode( ', ', $identifiers ) . ' { display: none !important; }' . '</style>';
75
  }
includes/class-wcj-checkout-custom-fields.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Checkout Custom Fields
4
  *
5
- * @version 3.2.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,7 @@ class WCJ_Checkout_Custom_Fields extends WCJ_Module {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 3.2.0
19
  */
20
  function __construct() {
21
 
@@ -34,7 +34,7 @@ class WCJ_Checkout_Custom_Fields extends WCJ_Module {
34
  add_action( 'woocommerce_admin_order_data_after_shipping_address', array( $this, 'add_custom_order_and_account_fields_to_admin_order_display' ), PHP_INT_MAX );
35
 
36
  if ( 'yes' === get_option( 'wcj_checkout_custom_fields_add_to_order_received', 'yes' ) ) {
37
- add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_custom_fields_to_order_display' ), PHP_INT_MAX );
38
  }
39
  add_action( 'woocommerce_email_after_order_table', array( $this, 'add_custom_fields_to_emails' ), PHP_INT_MAX, 2 );
40
 
@@ -157,20 +157,6 @@ class WCJ_Checkout_Custom_Fields extends WCJ_Module {
157
  return $field;
158
  }
159
 
160
- /**
161
- * add_custom_fields_to_emails.
162
- *
163
- * @version 2.3.0
164
- */
165
- function add_custom_fields_to_emails( $order, $sent_to_admin ) {
166
- if (
167
- ( $sent_to_admin && 'yes' === get_option( 'wcj_checkout_custom_fields_email_all_to_admin' ) ) ||
168
- ( ! $sent_to_admin && 'yes' === get_option( 'wcj_checkout_custom_fields_email_all_to_customer' ) )
169
- ) {
170
- $this->add_custom_fields_to_order_display( $order );
171
- }
172
- }
173
-
174
  /**
175
  * add_custom_fields_to_store_exporter_order.
176
  *
@@ -261,26 +247,60 @@ class WCJ_Checkout_Custom_Fields extends WCJ_Module {
261
  }
262
  }
263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  /**
265
  * add_custom_fields_to_order_display.
266
  *
267
- * @version 2.7.0
268
  * @since 2.3.0
 
269
  */
270
- function add_custom_fields_to_order_display( $order, $section = '', $add_styling = false ) {
271
- $post_meta = get_post_meta( wcj_get_order_id( $order ) );
272
  $final_output = '';
273
  foreach( $post_meta as $key => $values ) {
274
-
275
  if ( false !== strpos( $key, 'wcj_checkout_field_' ) && isset( $values[0] ) ) {
276
-
277
  if ( '' != $section ) {
278
  $the_section = strtok( $key, '_' );
279
  if ( $section !== $the_section ) {
280
  continue;
281
  }
282
  }
283
-
284
  if (
285
  false !== strpos( $key, '_label_' ) ||
286
  false !== strpos( $key, '_type_' ) ||
@@ -289,61 +309,46 @@ class WCJ_Checkout_Custom_Fields extends WCJ_Module {
289
  ) {
290
  continue;
291
  }
292
-
293
- $output = '';
294
-
295
  $the_label_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_label_', $key );
296
  if ( isset( $post_meta[ $the_label_key ][0] ) ) {
297
- $output .= $post_meta[ $the_label_key ][0] . ': ';
298
  } elseif ( is_array( $values[0] ) && isset( $values[0]['label'] ) ) {
299
- $output .= $values[0]['label'] . ': ';
300
- // TODO: convert from before version 2.3.0
301
- }
302
-
303
- if ( $add_styling && '' != $output ) {
304
- $output = '<strong>' . $output . '</strong>';
305
  }
306
-
307
- $the_value = ( is_array( $values[0] ) && isset( $values[0]['value'] ) ) ? $values[0]['value'] : $values[0];
308
-
309
- $the_type_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_type_', $key );
310
- if ( isset( $post_meta[ $the_type_key ][0] ) && 'checkbox' === $post_meta[ $the_type_key ][0] ) {
311
- $the_checkbox_value_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_checkbox_value_', $key );
312
- $output .= ( isset( $post_meta[ $the_checkbox_value_key ][0] ) ) ? $post_meta[ $the_checkbox_value_key ][0] : $the_value;
313
- } elseif ( isset( $post_meta[ $the_type_key ][0] ) && ( 'radio' === $post_meta[ $the_type_key ][0] || 'select' === $post_meta[ $the_type_key ][0] ) ) {
314
- $the_select_values_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_select_options_', $key );
315
- $the_select_values = ( isset( $post_meta[ $the_select_values_key ][0] ) ) ? $post_meta[ $the_select_values_key ][0] : '';
316
- if ( ! empty( $the_select_values ) ) {
317
- $the_select_values_prepared = wcj_get_select_options( $the_select_values );
318
- $is_found = false;
319
- foreach ( $the_select_values_prepared as $the_select_value_prepared_key => $the_select_value_prepared_value ) {
320
- if ( $the_value === $the_select_value_prepared_key ) {
321
- $output .= $the_select_value_prepared_value;
322
- $is_found = true;
323
- break;
324
- }
325
- }
326
- if ( ! $is_found ) {
327
- $output .= $the_value;
328
- }
329
  } else {
330
- $output .= $the_value;
331
  }
332
  } else {
333
- $output .= $the_value;
334
  }
335
-
336
- if ( '' != $output ) {
337
- $final_output .= $output . '<br>';
 
 
 
 
338
  }
339
  }
340
  }
 
341
  if ( '' != $final_output ) {
342
- if ( $add_styling ) {
343
- echo '<div class="clear"></div><p>' . $final_output . '</p>';
344
- } else {
345
- echo $final_output;
346
- }
347
  }
348
  }
349
 
@@ -437,11 +442,16 @@ class WCJ_Checkout_Custom_Fields extends WCJ_Module {
437
  /**
438
  * add_custom_order_and_account_fields_to_admin_order_display
439
  *
440
- * @version 2.5.0
441
  */
442
  function add_custom_order_and_account_fields_to_admin_order_display( $order ) {
443
- $this->add_custom_fields_to_order_display( $order, 'order', true );
444
- $this->add_custom_fields_to_order_display( $order, 'account', true );
 
 
 
 
 
445
  /*
446
  $fields = $this->add_woocommerce_admin_fields( $fields, 'order' );
447
  $fields = $this->add_woocommerce_admin_fields( $fields, 'account' );
2
  /**
3
  * Booster for WooCommerce - Module - Checkout Custom Fields
4
  *
5
+ * @version 3.2.2
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.2.2
19
  */
20
  function __construct() {
21
 
34
  add_action( 'woocommerce_admin_order_data_after_shipping_address', array( $this, 'add_custom_order_and_account_fields_to_admin_order_display' ), PHP_INT_MAX );
35
 
36
  if ( 'yes' === get_option( 'wcj_checkout_custom_fields_add_to_order_received', 'yes' ) ) {
37
+ add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_custom_fields_to_view_order_and_thankyou_pages' ), PHP_INT_MAX );
38
  }
39
  add_action( 'woocommerce_email_after_order_table', array( $this, 'add_custom_fields_to_emails' ), PHP_INT_MAX, 2 );
40
 
157
  return $field;
158
  }
159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  /**
161
  * add_custom_fields_to_store_exporter_order.
162
  *
247
  }
248
  }
249
 
250
+ /**
251
+ * add_custom_fields_to_emails.
252
+ *
253
+ * @version 3.2.2
254
+ */
255
+ function add_custom_fields_to_emails( $order, $sent_to_admin ) {
256
+ if (
257
+ ( $sent_to_admin && 'yes' === get_option( 'wcj_checkout_custom_fields_email_all_to_admin' ) ) ||
258
+ ( ! $sent_to_admin && 'yes' === get_option( 'wcj_checkout_custom_fields_email_all_to_customer' ) )
259
+ ) {
260
+ $templates = array(
261
+ 'before' => get_option( 'wcj_checkout_custom_fields_emails_template_before', '' ),
262
+ 'field' => get_option( 'wcj_checkout_custom_fields_emails_template_field', '<p><strong>%label%:</strong> %value%</p>' ),
263
+ 'after' => get_option( 'wcj_checkout_custom_fields_emails_template_after', '' ),
264
+ );
265
+ $this->add_custom_fields_to_order_display( $order, '', $templates );
266
+ }
267
+ }
268
+
269
+ /**
270
+ * add_custom_fields_to_view_order_and_thankyou_pages.
271
+ *
272
+ * @version 3.2.2
273
+ * @since 3.2.2
274
+ */
275
+ function add_custom_fields_to_view_order_and_thankyou_pages( $order ) {
276
+ $templates = array(
277
+ 'before' => get_option( 'wcj_checkout_custom_fields_order_received_template_before', '' ),
278
+ 'field' => get_option( 'wcj_checkout_custom_fields_order_received_template_field', '<p><strong>%label%:</strong> %value%</p>' ),
279
+ 'after' => get_option( 'wcj_checkout_custom_fields_order_received_template_after', '' ),
280
+ );
281
+ $this->add_custom_fields_to_order_display( $order, '', $templates );
282
+ }
283
+
284
  /**
285
  * add_custom_fields_to_order_display.
286
  *
287
+ * @version 3.2.2
288
  * @since 2.3.0
289
+ * @todo convert from before version 2.3.0
290
  */
291
+ function add_custom_fields_to_order_display( $order, $section = '', $templates ) {
292
+ $post_meta = get_post_meta( wcj_get_order_id( $order ) );
293
  $final_output = '';
294
  foreach( $post_meta as $key => $values ) {
 
295
  if ( false !== strpos( $key, 'wcj_checkout_field_' ) && isset( $values[0] ) ) {
296
+ // Checking section (if set)
297
  if ( '' != $section ) {
298
  $the_section = strtok( $key, '_' );
299
  if ( $section !== $the_section ) {
300
  continue;
301
  }
302
  }
303
+ // Skipping unnecessary meta
304
  if (
305
  false !== strpos( $key, '_label_' ) ||
306
  false !== strpos( $key, '_type_' ) ||
309
  ) {
310
  continue;
311
  }
312
+ // Field label
313
+ $label = '';
 
314
  $the_label_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_label_', $key );
315
  if ( isset( $post_meta[ $the_label_key ][0] ) ) {
316
+ $label = $post_meta[ $the_label_key ][0];
317
  } elseif ( is_array( $values[0] ) && isset( $values[0]['label'] ) ) {
318
+ $label = $values[0]['label'];
 
 
 
 
 
319
  }
320
+ // Field value
321
+ $value = '';
322
+ $_value = ( is_array( $values[0] ) && isset( $values[0]['value'] ) ? $values[0]['value'] : $values[0] );
323
+ $type_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_type_', $key );
324
+ if ( isset( $post_meta[ $type_key ][0] ) && 'checkbox' === $post_meta[ $type_key ][0] ) {
325
+ $checkbox_value_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_checkbox_value_', $key );
326
+ $value = ( isset( $post_meta[ $checkbox_value_key ][0] ) ? $post_meta[ $checkbox_value_key ][0] : $_value );
327
+ } elseif ( isset( $post_meta[ $type_key ][0] ) && ( 'radio' === $post_meta[ $type_key ][0] || 'select' === $post_meta[ $type_key ][0] ) ) {
328
+ $select_values_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_select_options_', $key );
329
+ $select_values = ( isset( $post_meta[ $select_values_key ][0] ) ) ? $post_meta[ $select_values_key ][0] : '';
330
+ if ( ! empty( $select_values ) ) {
331
+ $select_values_prepared = wcj_get_select_options( $select_values );
332
+ $value = ( isset( $select_values_prepared[ $_value ] ) ? $select_values_prepared[ $_value ] : $_value );
 
 
 
 
 
 
 
 
 
 
333
  } else {
334
+ $value = $_value;
335
  }
336
  } else {
337
+ $value = $_value;
338
  }
339
+ // Adding field to final output
340
+ if ( '' != $label || '' != $value ) {
341
+ $replaced_values = array(
342
+ '%label%' => $label,
343
+ '%value%' => $value,
344
+ );
345
+ $final_output .= str_replace( array_keys( $replaced_values ), $replaced_values, $templates['field'] );
346
  }
347
  }
348
  }
349
+ // Outputting
350
  if ( '' != $final_output ) {
351
+ echo $templates['before'] . $final_output . $templates['after'];
 
 
 
 
352
  }
353
  }
354
 
442
  /**
443
  * add_custom_order_and_account_fields_to_admin_order_display
444
  *
445
+ * @version 3.2.2
446
  */
447
  function add_custom_order_and_account_fields_to_admin_order_display( $order ) {
448
+ $templates = array(
449
+ 'before' => '<div class="clear"></div><p>',
450
+ 'field' => '<strong>%label%: </strong>%value%<br>',
451
+ 'after' => '</p>',
452
+ );
453
+ $this->add_custom_fields_to_order_display( $order, 'order', $templates );
454
+ $this->add_custom_fields_to_order_display( $order, 'account', $templates );
455
  /*
456
  $fields = $this->add_woocommerce_admin_fields( $fields, 'order' );
457
  $fields = $this->add_woocommerce_admin_fields( $fields, 'account' );
includes/class-wcj-currency-exchange-rates.php CHANGED
@@ -40,6 +40,7 @@ class WCJ_Currency_Exchange_Rates extends WCJ_Module {
40
  *
41
  * @version 2.7.0
42
  * @since 2.6.0
 
43
  */
44
  function wcj_ajax_get_exchange_rates() {
45
  echo alg_get_exchange_rate( $_POST['wcj_currency_from'], $_POST['wcj_currency_to'] );
40
  *
41
  * @version 2.7.0
42
  * @since 2.6.0
43
+ * @todo (maybe) move this to `class-wcj-exchange-rates.php`
44
  */
45
  function wcj_ajax_get_exchange_rates() {
46
  echo alg_get_exchange_rate( $_POST['wcj_currency_from'], $_POST['wcj_currency_to'] );
includes/class-wcj-emails.php CHANGED
@@ -87,7 +87,7 @@ class WCJ_Emails extends WCJ_Module {
87
  */
88
  function add_custom_woocommerce_email_actions( $email_actions ) {
89
  $email_actions[] = 'woocommerce_checkout_order_processed';
90
- $order_statuses = wcj_get_order_statuses_v2();
91
  foreach ( $order_statuses as $slug => $name ) {
92
  $email_actions[] = 'woocommerce_order_status_' . $slug;
93
  foreach ( $order_statuses as $slug2 => $name2 ) {
87
  */
88
  function add_custom_woocommerce_email_actions( $email_actions ) {
89
  $email_actions[] = 'woocommerce_checkout_order_processed';
90
+ $order_statuses = wcj_get_order_statuses();
91
  foreach ( $order_statuses as $slug => $name ) {
92
  $email_actions[] = 'woocommerce_order_status_' . $slug;
93
  foreach ( $order_statuses as $slug2 => $name2 ) {
includes/class-wcj-eu-vat-number.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - EU VAT Number
4
  *
5
- * @version 2.9.0
6
  * @since 2.3.9
7
  * @author Algoritmika Ltd.
8
  */
@@ -215,7 +215,7 @@ class WCJ_EU_VAT_Number extends WCJ_Module {
215
  /**
216
  * add_eu_vat_number_to_order_display.
217
  *
218
- * @version 2.7.0
219
  * @since 2.4.7
220
  */
221
  function add_eu_vat_number_to_order_display( $order ) {
@@ -225,7 +225,7 @@ class WCJ_EU_VAT_Number extends WCJ_Module {
225
  $the_eu_vat_number = get_post_meta( $order_id, $option_name, true );
226
  if ( '' != $the_eu_vat_number ) {
227
  $the_label = get_option( 'wcj_eu_vat_number_field_label', __( 'EU VAT Number', 'woocommerce-jetpack' ) );
228
- $html .= $the_label . ': ' . $the_eu_vat_number . '<br>';
229
  }
230
  echo $html;
231
  }
2
  /**
3
  * Booster for WooCommerce - Module - EU VAT Number
4
  *
5
+ * @version 3.2.2
6
  * @since 2.3.9
7
  * @author Algoritmika Ltd.
8
  */
215
  /**
216
  * add_eu_vat_number_to_order_display.
217
  *
218
+ * @version 3.2.2
219
  * @since 2.4.7
220
  */
221
  function add_eu_vat_number_to_order_display( $order ) {
225
  $the_eu_vat_number = get_post_meta( $order_id, $option_name, true );
226
  if ( '' != $the_eu_vat_number ) {
227
  $the_label = get_option( 'wcj_eu_vat_number_field_label', __( 'EU VAT Number', 'woocommerce-jetpack' ) );
228
+ $html .= '<p>' . '<strong>' . $the_label . '</strong>: ' . $the_eu_vat_number . '</p>';
229
  }
230
  echo $html;
231
  }
includes/class-wcj-multicurrency.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Multicurrency (Currency Switcher)
4
  *
5
- * @version 3.2.0
6
  * @since 2.4.3
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Multicurrency extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 3.1.2
20
  */
21
  function __construct() {
22
 
@@ -31,6 +31,9 @@ class WCJ_Multicurrency extends WCJ_Module {
31
  parent::__construct();
32
 
33
  if ( $this->is_enabled() ) {
 
 
 
34
  // add_filter( 'init', array( $this, 'add_hooks' ) );
35
  $this->add_hooks();
36
 
@@ -48,7 +51,8 @@ class WCJ_Multicurrency extends WCJ_Module {
48
  /**
49
  * add_hooks.
50
  *
51
- * @version 3.1.2
 
52
  */
53
  function add_hooks() {
54
  // Session
@@ -71,7 +75,7 @@ class WCJ_Multicurrency extends WCJ_Module {
71
  add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX - 1, 1 );
72
 
73
  // Add "Change Price" hooks
74
- wcj_add_change_price_hooks( $this, PHP_INT_MAX - 1 );
75
 
76
  // "WooCommerce Product Add-ons" plugin
77
  add_filter( 'get_product_addons', array( $this, 'change_price_addons' ) );
@@ -81,7 +85,7 @@ class WCJ_Multicurrency extends WCJ_Module {
81
  if ( ! empty( $this->additional_price_filters ) ) {
82
  $this->additional_price_filters = array_map( 'trim', explode( PHP_EOL, $this->additional_price_filters ) );
83
  foreach ( $this->additional_price_filters as $additional_price_filter ) {
84
- add_filter( $additional_price_filter, array( $this, 'change_price' ), PHP_INT_MAX - 1, 2 );
85
  }
86
  } else {
87
  $this->additional_price_filters = array();
2
  /**
3
  * Booster for WooCommerce - Module - Multicurrency (Currency Switcher)
4
  *
5
+ * @version 3.2.2
6
  * @since 2.4.3
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.2.2
20
  */
21
  function __construct() {
22
 
31
  parent::__construct();
32
 
33
  if ( $this->is_enabled() ) {
34
+
35
+ $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'multicurrency' );
36
+
37
  // add_filter( 'init', array( $this, 'add_hooks' ) );
38
  $this->add_hooks();
39
 
51
  /**
52
  * add_hooks.
53
  *
54
+ * @version 3.2.2
55
+ * @todo (maybe) replace all `PHP_INT_MAX - 1` with `$this->price_hooks_priority`
56
  */
57
  function add_hooks() {
58
  // Session
75
  add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX - 1, 1 );
76
 
77
  // Add "Change Price" hooks
78
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority );
79
 
80
  // "WooCommerce Product Add-ons" plugin
81
  add_filter( 'get_product_addons', array( $this, 'change_price_addons' ) );
85
  if ( ! empty( $this->additional_price_filters ) ) {
86
  $this->additional_price_filters = array_map( 'trim', explode( PHP_EOL, $this->additional_price_filters ) );
87
  foreach ( $this->additional_price_filters as $additional_price_filter ) {
88
+ add_filter( $additional_price_filter, array( $this, 'change_price' ), $this->price_hooks_priority, 2 );
89
  }
90
  } else {
91
  $this->additional_price_filters = array();
includes/class-wcj-my-account.php CHANGED
@@ -44,7 +44,7 @@ class WCJ_My_Account extends WCJ_Module {
44
  function maybe_add_my_account_order_actions( $actions, $order ) {
45
  $statuses_to_add = get_option( 'wcj_my_account_add_order_status_actions', '' );
46
  if ( ! empty( $statuses_to_add ) ) {
47
- $all_statuses = wcj_get_order_statuses_v2();
48
  foreach ( $statuses_to_add as $status_to_add ) {
49
  if ( $status_to_add != $order->get_status() ) {
50
  $actions[ 'wcj_mark_' . $status_to_add . '_by_customer' ] = array(
44
  function maybe_add_my_account_order_actions( $actions, $order ) {
45
  $statuses_to_add = get_option( 'wcj_my_account_add_order_status_actions', '' );
46
  if ( ! empty( $statuses_to_add ) ) {
47
+ $all_statuses = wcj_get_order_statuses();
48
  foreach ( $statuses_to_add as $status_to_add ) {
49
  if ( $status_to_add != $order->get_status() ) {
50
  $actions[ 'wcj_mark_' . $status_to_add . '_by_customer' ] = array(
includes/class-wcj-order-custom-statuses.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Order Custom Statuses
4
  *
5
- * @version 3.1.2
6
  * @since 2.2.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,9 +16,10 @@ class WCJ_Order_Custom_Statuses extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 3.1.2
20
- * @todo copy all changes from Custom Order Status plugin
21
  * @todo `wcj_orders_custom_statuses_processing_and_completed_actions` to Custom Order Status plugin
 
22
  */
23
  function __construct() {
24
 
@@ -31,17 +32,17 @@ class WCJ_Order_Custom_Statuses extends WCJ_Module {
31
  $this->add_tools( array(
32
  'custom_statuses' => array(
33
  'title' => __( 'Custom Statuses', 'woocommerce-jetpack' ),
34
- 'desc' => __( 'Tool lets you add or delete any custom status for WooCommerce orders.', 'woocommerce-jetpack' ),
35
  ),
36
  ) );
37
 
38
  if ( $this->is_enabled() ) {
39
 
40
- add_filter( 'wc_order_statuses', array( $this, 'add_custom_statuses_to_filter' ), 100 );
41
  add_action( 'init', array( $this, 'register_custom_post_statuses' ) );
42
  add_action( 'admin_head', array( $this, 'hook_statuses_icons_css' ) );
43
 
44
- add_filter( 'woocommerce_default_order_status', array( $this, 'set_default_order_status' ), 100 );
45
 
46
  if ( 'yes' === get_option( 'wcj_orders_custom_statuses_add_to_reports' ) ) {
47
  add_filter( 'woocommerce_reports_order_statuses', array( $this, 'add_custom_order_statuses_to_reports' ), PHP_INT_MAX );
@@ -65,6 +66,10 @@ class WCJ_Order_Custom_Statuses extends WCJ_Module {
65
  add_filter( 'wc_order_is_editable', array( $this, 'add_custom_order_statuses_to_order_editable' ), PHP_INT_MAX, 2 );
66
  }
67
 
 
 
 
 
68
  }
69
  }
70
 
@@ -104,11 +109,11 @@ class WCJ_Order_Custom_Statuses extends WCJ_Module {
104
  /**
105
  * add_custom_status_to_processing_and_completed_actions.
106
  *
107
- * @version 2.8.0
108
  * @since 2.8.0
109
  */
110
  function add_custom_status_to_processing_and_completed_actions( $actions, $_order ) {
111
- $custom_order_statuses = get_option( 'wcj_orders_custom_statuses_array' );
112
  if ( ! empty( $custom_order_statuses ) && is_array( $custom_order_statuses ) ) {
113
  $custom_order_statuses_without_wc_prefix = array();
114
  foreach ( $custom_order_statuses as $slug => $label ) {
@@ -117,16 +122,24 @@ class WCJ_Order_Custom_Statuses extends WCJ_Module {
117
  global $post;
118
  $default_actions = array();
119
  $show = apply_filters( 'booster_get_option', 'hide', get_option( 'wcj_orders_custom_statuses_processing_and_completed_actions', 'hide' ) );
120
- if ( ( 'show_both' === $show || 'show_processing' === $show ) && $_order->has_status( array_merge( array( 'pending', 'on-hold' ), $custom_order_statuses_without_wc_prefix ) ) ) {
 
 
 
121
  $default_actions['processing'] = array(
122
- 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=processing&order_id=' . $post->ID ), 'woocommerce-mark-order-status' ),
 
123
  'name' => __( 'Processing', 'woocommerce' ),
124
  'action' => "processing",
125
  );
126
  }
127
- if ( ( 'show_both' === $show || 'show_complete' === $show ) && $_order->has_status( array_merge( array( 'pending', 'on-hold', 'processing' ), $custom_order_statuses_without_wc_prefix ) ) ) {
 
 
 
128
  $default_actions['complete'] = array(
129
- 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=completed&order_id=' . $post->ID ), 'woocommerce-mark-order-status' ),
 
130
  'name' => __( 'Complete', 'woocommerce' ),
131
  'action' => "complete",
132
  );
@@ -139,17 +152,18 @@ class WCJ_Order_Custom_Statuses extends WCJ_Module {
139
  /**
140
  * add_custom_status_actions_buttons.
141
  *
142
- * @version 2.7.0
143
  * @since 2.6.0
144
  */
145
  function add_custom_status_actions_buttons( $actions, $_order ) {
146
- $custom_order_statuses = get_option( 'wcj_orders_custom_statuses_array' );
147
  if ( ! empty( $custom_order_statuses ) && is_array( $custom_order_statuses ) ) {
148
  foreach ( $custom_order_statuses as $slug => $label ) {
149
  $custom_order_status = substr( $slug, 3 );
150
  if ( ! $_order->has_status( array( $custom_order_status ) ) ) { // if order status is not $custom_order_status
151
  $actions[ $custom_order_status ] = array(
152
- 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=' . $custom_order_status . '&order_id=' . wcj_get_order_id( $_order ) ), 'woocommerce-mark-order-status' ),
 
153
  'name' => $label,
154
  'action' => "view " . $custom_order_status, // setting "view" for proper button CSS
155
  );
@@ -160,77 +174,70 @@ class WCJ_Order_Custom_Statuses extends WCJ_Module {
160
  }
161
 
162
  /**
163
- * add_custom_status_actions_buttons_css.
164
  *
165
- * @version 2.6.0
166
- * @since 2.6.0
167
  */
168
- function add_custom_status_actions_buttons_css() {
169
- $custom_order_statuses = get_option( 'wcj_orders_custom_statuses_array' );
170
- if ( ! empty( $custom_order_statuses ) && is_array( $custom_order_statuses ) ) {
171
- foreach ( $custom_order_statuses as $slug => $label ) {
172
- $custom_order_status = substr( $slug, 3 );
173
- if ( '' != ( $icon_data = get_option( 'wcj_orders_custom_status_icon_data_' . $custom_order_status, '' ) ) ) {
174
- $content = $icon_data['content'];
175
- $color = $icon_data['color'];
176
- } else {
177
- $content = 'e011';
178
- $color = '#999999';
179
- }
180
- $color_style = ( 'yes' === apply_filters( 'booster_get_option', 'no', get_option( 'wcj_orders_custom_statuses_add_to_order_list_actions_colored', 'no' ) ) ) ? ' color: ' . $color . ' !important;' : '';
181
- echo '<style>.view.' . $custom_order_status . '::after { font-family: WooCommerce !important;' . $color_style . ' content: "\\' . $content . '" !important; }</style>';
182
- }
183
  }
 
184
  }
185
 
186
  /**
187
- * get_default_order_statuses.
188
  *
189
- * @version 2.5.6
190
- * @since 2.5.6
191
  */
192
- function get_default_order_statuses() {
193
- return array(
194
- 'wc-pending' => _x( 'Pending payment', 'Order status', 'woocommerce' ),
195
- 'wc-processing' => _x( 'Processing', 'Order status', 'woocommerce' ),
196
- 'wc-on-hold' => _x( 'On hold', 'Order status', 'woocommerce' ),
197
- 'wc-completed' => _x( 'Completed', 'Order status', 'woocommerce' ),
198
- 'wc-cancelled' => _x( 'Cancelled', 'Order status', 'woocommerce' ),
199
- 'wc-refunded' => _x( 'Refunded', 'Order status', 'woocommerce' ),
200
- 'wc-failed' => _x( 'Failed', 'Order status', 'woocommerce' ),
201
- );
202
  }
203
 
204
  /**
205
  * add_custom_order_statuses_to_reports.
206
  *
207
- * @version 2.3.8
208
  */
209
  function add_custom_order_statuses_to_reports( $order_statuses ) {
210
  if ( is_array( $order_statuses ) && in_array( 'completed', $order_statuses ) ) {
211
- $custom_order_statuses = get_option( 'wcj_orders_custom_statuses_array' );
212
- if ( ! empty( $custom_order_statuses ) && is_array( $custom_order_statuses ) ) {
213
- foreach ( $custom_order_statuses as $slug => $label ) {
214
- $order_statuses[] = substr( $slug, 3 );
215
- }
216
- }
217
  }
218
- return $order_statuses;
219
  }
220
 
221
  /**
222
  * set_default_order_status.
 
 
223
  */
224
- function set_default_order_status() {
225
- return get_option( 'wcj_orders_custom_statuses_default_status', 'pending' );
226
  }
227
 
228
  /**
229
  * register_custom_post_statuses.
 
 
230
  */
231
  function register_custom_post_statuses() {
232
- $wcj_orders_custom_statuses_array = ( '' == get_option( 'wcj_orders_custom_statuses_array' ) ) ? array() : get_option( 'wcj_orders_custom_statuses_array' );
233
- foreach ( $wcj_orders_custom_statuses_array as $slug => $label )
234
  register_post_status( $slug, array(
235
  'label' => $label,
236
  'public' => true,
@@ -244,197 +251,39 @@ class WCJ_Order_Custom_Statuses extends WCJ_Module {
244
 
245
  /**
246
  * add_custom_statuses_to_filter.
 
 
247
  */
248
  function add_custom_statuses_to_filter( $order_statuses ) {
249
- $wcj_orders_custom_statuses_array = ( '' == get_option( 'wcj_orders_custom_statuses_array' ) ) ? array() : get_option( 'wcj_orders_custom_statuses_array' );
250
- $order_statuses = ( '' == $order_statuses ) ? array() : $order_statuses;
251
- return array_merge( $order_statuses, $wcj_orders_custom_statuses_array );
252
  }
253
 
254
  /**
255
  * hook_statuses_icons_css.
256
  *
257
- * @verison 2.5.6
258
  */
259
  function hook_statuses_icons_css() {
260
- $output = '<style>';
261
- $statuses = function_exists( 'wc_get_order_statuses' ) ? wc_get_order_statuses() : array();
262
- $default_statuses = $this->get_default_order_statuses();
263
  foreach( $statuses as $status => $status_name ) {
264
- if ( ! array_key_exists( $status, $default_statuses ) ) {
265
- if ( '' != ( $icon_data = get_option( 'wcj_orders_custom_status_icon_data_' . substr( $status, 3 ), '' ) ) ) {
266
- $content = $icon_data['content'];
267
- $color = $icon_data['color'];
268
- } else {
269
- $content = 'e011';
270
- $color = '#999999';
271
- }
272
- $output .= 'mark.' . substr( $status, 3 ) . '::after { content: "\\' . $content . '"; color: ' . $color . '; }';
273
- $output .= 'mark.' . substr( $status, 3 ) . ':after {font-family:WooCommerce;speak:none;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;margin:0;text-indent:0;position:absolute;top:0;left:0;width:100%;height:100%;text-align:center}';
274
- }
275
- }
276
- // $output .= '.close:after { content: "\e011"; }';
277
- $output .= '</style>';
278
- echo $output;
279
- }
280
-
281
- /**
282
- * Add new custom status to wcj_orders_custom_statuses_array.
283
- *
284
- * @version 2.6.0
285
- */
286
- function add_custom_status( $new_status, $new_status_label, $new_status_icon_content, $new_status_icon_color ) {
287
-
288
- // Checking function arguments
289
- if ( ! isset( $new_status ) || '' == $new_status ) {
290
- return '<div class="error"><p>' . __( 'Status slug is empty. Status was not added!', 'woocommerce-jetpack' ) . '</p></div>';
291
- }
292
- if ( strlen( $new_status ) > 17 ) {
293
- return '<div class="error"><p>' . __( 'The length of status slug must be 17 or less characters. Status was not added!', 'woocommerce-jetpack' ) . '</p></div>';
294
- }
295
- if ( ! isset( $new_status_label ) || '' == $new_status_label ) {
296
- return '<div class="error"><p>' . __( 'Status label is empty. Status was not added!', 'woocommerce-jetpack' ) . '</p></div>';
297
- }
298
-
299
- // Checking status
300
- $statuses_updated = ( '' == get_option( 'wcj_orders_custom_statuses_array' ) ) ? array() : get_option( 'wcj_orders_custom_statuses_array' );
301
- $new_key = 'wc-' . $_POST['new_status'];
302
- if ( isset( $statuses_updated[ $new_key ] ) ) {
303
- return '<div class="error"><p>' . __( 'Duplicate slug. Status was not added!', 'woocommerce-jetpack' ) . '</p></div>';
304
  }
305
- $default_statuses = $this->get_default_order_statuses();
306
- if ( isset( $default_statuses[ $new_key ] ) ) {
307
- return '<div class="error"><p>' . __( 'Duplicate slug (default WooCommerce status). Status was not added!', 'woocommerce-jetpack' ) . '</p></div>';
308
- }
309
- $statuses_updated[ $new_key ] = $_POST['new_status_label'];
310
-
311
- // Adding custom status
312
- $result = update_option( 'wcj_orders_custom_statuses_array', $statuses_updated );
313
- $result = update_option( 'wcj_orders_custom_status_icon_data_' . $new_status, array(
314
- 'content' => $new_status_icon_content,
315
- 'color' => $new_status_icon_color,
316
- ) );
317
- if ( true === $result ) {
318
- return '<div class="updated"><p>' . __( 'New status has been successfully added!', 'woocommerce-jetpack' ) . '</p></div>';
319
- } else {
320
- return '<div class="error"><p>' . __( 'Status was not added.', 'woocommerce-jetpack' ) . '</p></div>';
321
  }
322
  }
323
 
324
  /**
325
  * create_custom_statuses_tool.
326
  *
327
- * @version 2.6.0
328
- * @todo (from Custom Order Status for WooCommerce plugin) delete: change all orders to fallback status
329
- * @todo (from Custom Order Status for WooCommerce plugin) delete: option to change fallback status from 'on-hold' to any other status
330
- * @todo (from Custom Order Status for WooCommerce plugin) delete: delete icon data
331
  */
332
  function create_custom_statuses_tool() {
333
- $result_message = '';
334
- if ( isset( $_POST['add_custom_status'] ) ) {
335
- $result_message = $this->add_custom_status( $_POST['new_status'], $_POST['new_status_label'], $_POST['new_status_icon_content'], $_POST['new_status_icon_color'] );
336
- } elseif ( isset( $_POST['edit_custom_status'] ) ) {
337
- if ( ! isset( $_POST['new_status_label'] ) || '' == $_POST['new_status_label'] ) {
338
- $result_message = '<div class="error"><p>' . __( 'Status label is empty. Status was not edited!', 'woocommerce-jetpack' ) . '</p></div>';
339
- } else {
340
- $statuses_updated = ( '' == get_option( 'wcj_orders_custom_statuses_array' ) ) ? array() : get_option( 'wcj_orders_custom_statuses_array' );
341
- $statuses_updated[ 'wc-' . $_POST['new_status'] ] = $_POST['new_status_label'];
342
- $result = update_option( 'wcj_orders_custom_statuses_array', $statuses_updated );
343
- $result_icon_data = update_option( 'wcj_orders_custom_status_icon_data_' . $_POST['new_status'], array(
344
- 'content' => $_POST['new_status_icon_content'],
345
- 'color' => $_POST['new_status_icon_color'],
346
- ) );
347
- if ( $result || $result_icon_data ) {
348
- $result_message = '<div class="updated"><p>' . __( 'Status has been successfully edited!', 'woocommerce-jetpack' ) . '</p></div>';
349
- } else {
350
- $result_message = '<div class="error"><p>' . __( 'Status was not edited.', 'woocommerce-jetpack' ) . '</p></div>';
351
- }
352
- }
353
- } elseif ( isset( $_GET['delete'] ) && ( '' != $_GET['delete'] ) ) {
354
- $statuses_updated = apply_filters( 'wc_order_statuses', array() );
355
- unset( $statuses_updated[ $_GET['delete'] ] );
356
- $result = update_option( 'wcj_orders_custom_statuses_array', $statuses_updated );
357
- if ( true === $result ) {
358
- $result_message = '<div class="updated"><p>' . __( 'Status has been successfully deleted.', 'woocommerce-jetpack' ) . '</p></div>';
359
- } else {
360
- $result_message = '<div class="error"><p>' . __( 'Delete failed.', 'woocommerce-jetpack' ) . '</p></div>';
361
- }
362
- }
363
- echo '<p>' . $this->get_back_to_settings_link_html() . '</p>';
364
- ?><div>
365
- <h2><?php echo __( 'Booster - Custom Statuses', 'woocommerce-jetpack' ); ?></h2>
366
- <p><?php echo __( 'The tool lets you add or delete any custom status for WooCommerce orders.', 'woocommerce-jetpack' ); ?></p>
367
- <?php echo $result_message; ?>
368
- <h3><?php echo __( 'Statuses', 'woocommerce-jetpack' ); ?></h3>
369
- <table class="wc_status_table widefat"><?php
370
- echo '<tr>';
371
- echo '<th>' . __( 'Slug', 'woocommerce-jetpack' ) . '</th>';
372
- echo '<th>' . __( 'Label', 'woocommerce-jetpack' ) . '</th>';
373
- echo '<th>' . __( 'Icon Code', 'woocommerce-jetpack' ) . '</th>';
374
- echo '<th>' . __( 'Icon Color', 'woocommerce-jetpack' ) . '</th>';
375
- echo '<th>' . __( 'Actions', 'woocommerce-jetpack' ) . '</th>';
376
- echo '</tr>';
377
- $statuses = function_exists( 'wc_get_order_statuses' ) ? wc_get_order_statuses() : array();
378
- $default_statuses = $this->get_default_order_statuses();
379
- foreach( $statuses as $status => $status_name ) {
380
- echo '<tr>';
381
- echo '<td>' . esc_attr( $status ) . '</td>';
382
- echo '<td>' . esc_html( $status_name ) . '</td>';
383
- if ( array_key_exists( $status, $default_statuses ) ) {
384
- echo '<td></td>';
385
- echo '<td></td>';
386
- echo '<td></td>';
387
- } else {
388
- if ( '' != ( $icon_data = get_option( 'wcj_orders_custom_status_icon_data_' . substr( $status, 3 ), '' ) ) ) {
389
- $content = $icon_data['content'];
390
- $color = $icon_data['color'];
391
- } else {
392
- $content = 'e011';
393
- $color = '#999999';
394
- }
395
- echo '<td>' . $content . '</td>';
396
- echo '<td>' . '<input disabled type="color" value="' . $color . '">' . '</td>';
397
- echo '<td>' . '<a class="button-primary" href="' . add_query_arg( 'delete', $status, remove_query_arg( 'edit' ) ) . '" onclick="return confirm(\'' . __( 'Are you sure?', 'woocommerce-jetpack' ) . '\')">' . __( 'Delete', 'woocommerce-jetpack' ) . '</a>';
398
- echo ' ' . '<a class="button-primary"' . ( '' != apply_filters( 'booster_get_message', '', 'desc' ) ? ' disabled title="' . __( 'Get Booster Plus to enable.', 'woocommerce-jetpack' ) . '"' : ' href="' . add_query_arg( 'edit', $status, remove_query_arg( 'delete' ) ) . '"' ) . '>' . __( 'Edit', 'woocommerce-jetpack' ) . '</a>' . '</td>';
399
- }
400
- echo '</tr>';
401
- }
402
- ?></table>
403
- <p></p>
404
- </div><?php
405
- $is_editing = ( isset( $_GET['edit'] ) ) ? true : false;
406
- if ( $is_editing ) {
407
- $edit_slug = $_GET['edit'];
408
- $custom_order_statuses = get_option( 'wcj_orders_custom_statuses_array' );
409
- $edit_label = isset( $custom_order_statuses[ $edit_slug ] ) ? $custom_order_statuses[ $edit_slug ] : '';
410
- if ( '' != ( $edit_icon_data = get_option( 'wcj_orders_custom_status_icon_data_' . substr( $edit_slug, 3 ), '' ) ) ) {
411
- $edit_content = $edit_icon_data['content'];
412
- $edit_color = $edit_icon_data['color'];
413
- } else {
414
- $edit_content = 'e011';
415
- $edit_color = '#999999';
416
- }
417
- }
418
- $icon_code_input_html = '<input type="text" name="new_status_icon_content" value="' . ( $is_editing ? $edit_content : 'e011' ) . '">';
419
- $icon_color_input_html = '<input type="color" name="new_status_icon_color" value="' . ( $is_editing ? $edit_color : '#999999' ) . '">';
420
- ?><div class="metabox-holder" style="width:300px;">
421
- <div class="postbox">
422
- <h3 class="hndle"><span><?php ( $is_editing ? _e( 'Edit', 'woocommerce-jetpack' ) : _e( 'Add', 'woocommerce-jetpack' ) ); ?></span></h3>
423
- <div class="inside">
424
- <form method="post" action="<?php echo remove_query_arg( 'delete' ); ?>">
425
- <ul>
426
- <li><?php _e( 'Slug (without wc- prefix)', 'woocommerce-jetpack' ); ?> <input type="text" name="new_status" style="width:100%;"<?php if ( $is_editing ) { echo ' value="' . substr( $edit_slug, 3 ) . '" readonly'; } ?>></li>
427
- <li><?php _e( 'Label', 'woocommerce-jetpack' ); ?> <input type="text" name="new_status_label" style="width:100%;"<?php if ( $is_editing ) { echo ' value="' . $edit_label . '"'; } ?>></li>
428
- <li><?php _e( 'Icon Code', 'woocommerce-jetpack' ); echo ' ' . $icon_code_input_html; ?><br><?php
429
- echo '<em>' . sprintf( __( 'You can check icon codes <a target="_blank" href="%s">here</a>.', 'woocommerce-jetpack' ), 'https://rawgit.com/woothemes/woocommerce-icons/master/demo.html' ) . '</em>'; ?></li>
430
- <li><?php _e( 'Icon Color', 'woocommerce-jetpack' ); echo ' ' . $icon_color_input_html; ?></li>
431
- </ul>
432
- <input class="button-primary" type="submit" name="<?php echo ( $is_editing ) ? 'edit_custom_status' : 'add_custom_status'; ?>" value="<?php ( $is_editing ? _e( 'Edit custom status', 'woocommerce-jetpack' ) : _e( 'Add new custom status', 'woocommerce-jetpack' ) ); ?>">
433
- <?php if ( $is_editing ) { echo ' <a class="button-primary" href="' . remove_query_arg( array( 'delete', 'edit' ) ) . '">' . __( 'Clear', 'woocommerce-jetpack' ) . '</a>'; } ?>
434
- </form>
435
- </div>
436
- </div>
437
- </div><?php
438
  }
439
 
440
  /**
@@ -442,38 +291,26 @@ class WCJ_Order_Custom_Statuses extends WCJ_Module {
442
  *
443
  * Using Javascript until WordPress core fixes: http://core.trac.wordpress.org/ticket/16031
444
  *
445
- * @version 2.2.7
446
  * @since 2.2.7
447
  */
448
  function bulk_admin_footer() {
449
  global $post_type;
450
  if ( 'shop_order' == $post_type ) {
451
  ?><script type="text/javascript"><?php
452
- foreach( $this->get_order_statuses() as $key => $order_status ) {
453
  if ( in_array( $key, array( 'processing', 'on-hold', 'completed', ) ) ) continue;
454
  ?>jQuery(function() {
455
- jQuery('<option>').val('mark_<?php echo $key; ?>').text('<?php echo __( 'Mark', 'woocommerce-jetpack' ) . ' ' . $order_status; ?>').appendTo('select[name="action"]');
456
- jQuery('<option>').val('mark_<?php echo $key; ?>').text('<?php echo __( 'Mark', 'woocommerce-jetpack' ) . ' ' . $order_status; ?>').appendTo('select[name="action2"]');
 
 
457
  });<?php
458
  }
459
  ?></script><?php
460
  }
461
  }
462
 
463
- /**
464
- * get_order_statuses.
465
- *
466
- * @todo use `wcj_get_order_statuses_v2`
467
- */
468
- function get_order_statuses() {
469
- $result = array();
470
- $statuses = function_exists( 'wc_get_order_statuses' ) ? wc_get_order_statuses() : array();
471
- foreach( $statuses as $status => $status_name ) {
472
- $result[ substr( $status, 3 ) ] = $statuses[ $status ];
473
- }
474
- return $result;
475
- }
476
-
477
  }
478
 
479
  endif;
2
  /**
3
  * Booster for WooCommerce - Module - Order Custom Statuses
4
  *
5
+ * @version 3.2.2
6
  * @since 2.2.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.2.2
20
+ * @todo check all changes from Custom Order Status plugin
21
  * @todo `wcj_orders_custom_statuses_processing_and_completed_actions` to Custom Order Status plugin
22
+ * @todo (maybe) add options to change icon and icon's color for all statuses (i.e. not only custom)
23
  */
24
  function __construct() {
25
 
32
  $this->add_tools( array(
33
  'custom_statuses' => array(
34
  'title' => __( 'Custom Statuses', 'woocommerce-jetpack' ),
35
+ 'desc' => __( 'Tool lets you add, edit or delete any custom status for WooCommerce orders.', 'woocommerce-jetpack' ),
36
  ),
37
  ) );
38
 
39
  if ( $this->is_enabled() ) {
40
 
41
+ add_filter( 'wc_order_statuses', array( $this, 'add_custom_statuses_to_filter' ), PHP_INT_MAX );
42
  add_action( 'init', array( $this, 'register_custom_post_statuses' ) );
43
  add_action( 'admin_head', array( $this, 'hook_statuses_icons_css' ) );
44
 
45
+ add_filter( 'woocommerce_default_order_status', array( $this, 'set_default_order_status' ), PHP_INT_MAX );
46
 
47
  if ( 'yes' === get_option( 'wcj_orders_custom_statuses_add_to_reports' ) ) {
48
  add_filter( 'woocommerce_reports_order_statuses', array( $this, 'add_custom_order_statuses_to_reports' ), PHP_INT_MAX );
66
  add_filter( 'wc_order_is_editable', array( $this, 'add_custom_order_statuses_to_order_editable' ), PHP_INT_MAX, 2 );
67
  }
68
 
69
+ // "Order Statuses" tool
70
+ include_once( 'tools/class-wcj-order-statuses-tool.php' );
71
+ $this->custom_statuses_tool = new WCJ_Order_Statuses_Tool( 'custom_statuses', $this );
72
+
73
  }
74
  }
75
 
109
  /**
110
  * add_custom_status_to_processing_and_completed_actions.
111
  *
112
+ * @version 3.2.2
113
  * @since 2.8.0
114
  */
115
  function add_custom_status_to_processing_and_completed_actions( $actions, $_order ) {
116
+ $custom_order_statuses = $this->get_custom_order_statuses();
117
  if ( ! empty( $custom_order_statuses ) && is_array( $custom_order_statuses ) ) {
118
  $custom_order_statuses_without_wc_prefix = array();
119
  foreach ( $custom_order_statuses as $slug => $label ) {
122
  global $post;
123
  $default_actions = array();
124
  $show = apply_filters( 'booster_get_option', 'hide', get_option( 'wcj_orders_custom_statuses_processing_and_completed_actions', 'hide' ) );
125
+ if (
126
+ ( 'show_both' === $show || 'show_processing' === $show ) &&
127
+ $_order->has_status( array_merge( array( 'pending', 'on-hold' ), $custom_order_statuses_without_wc_prefix ) )
128
+ ) {
129
  $default_actions['processing'] = array(
130
+ 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=processing&order_id=' . $post->ID ),
131
+ 'woocommerce-mark-order-status' ),
132
  'name' => __( 'Processing', 'woocommerce' ),
133
  'action' => "processing",
134
  );
135
  }
136
+ if (
137
+ ( 'show_both' === $show || 'show_complete' === $show ) &&
138
+ $_order->has_status( array_merge( array( 'pending', 'on-hold', 'processing' ), $custom_order_statuses_without_wc_prefix ) )
139
+ ) {
140
  $default_actions['complete'] = array(
141
+ 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=completed&order_id=' . $post->ID ),
142
+ 'woocommerce-mark-order-status' ),
143
  'name' => __( 'Complete', 'woocommerce' ),
144
  'action' => "complete",
145
  );
152
  /**
153
  * add_custom_status_actions_buttons.
154
  *
155
+ * @version 3.2.2
156
  * @since 2.6.0
157
  */
158
  function add_custom_status_actions_buttons( $actions, $_order ) {
159
+ $custom_order_statuses = $this->get_custom_order_statuses();
160
  if ( ! empty( $custom_order_statuses ) && is_array( $custom_order_statuses ) ) {
161
  foreach ( $custom_order_statuses as $slug => $label ) {
162
  $custom_order_status = substr( $slug, 3 );
163
  if ( ! $_order->has_status( array( $custom_order_status ) ) ) { // if order status is not $custom_order_status
164
  $actions[ $custom_order_status ] = array(
165
+ 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=' . $custom_order_status . '&order_id=' .
166
+ wcj_get_order_id( $_order ) ), 'woocommerce-mark-order-status' ),
167
  'name' => $label,
168
  'action' => "view " . $custom_order_status, // setting "view" for proper button CSS
169
  );
174
  }
175
 
176
  /**
177
+ * get_status_icon_data.
178
  *
179
+ * @version 3.2.2
180
+ * @since 3.2.2
181
  */
182
+ function get_status_icon_data( $status_slug_without_wc_prefix ) {
183
+ $return = array(
184
+ 'content' => 'e011',
185
+ 'color' => '#999999',
186
+ );
187
+ if ( '' != ( $icon_data = get_option( 'wcj_orders_custom_status_icon_data_' . $status_slug_without_wc_prefix, '' ) ) ) {
188
+ $return['content'] = $icon_data['content'];
189
+ $return['color'] = $icon_data['color'];
 
 
 
 
 
 
 
190
  }
191
+ return $return;
192
  }
193
 
194
  /**
195
+ * add_custom_status_actions_buttons_css.
196
  *
197
+ * @version 3.2.2
198
+ * @since 2.6.0
199
  */
200
+ function add_custom_status_actions_buttons_css() {
201
+ $custom_order_statuses = $this->get_custom_order_statuses( true );
202
+ foreach ( $custom_order_statuses as $slug => $label ) {
203
+ $icon_data = $this->get_status_icon_data( $slug );
204
+ $color_style = ( 'yes' === apply_filters( 'booster_get_option', 'no', get_option( 'wcj_orders_custom_statuses_add_to_order_list_actions_colored', 'no' ) ) ) ?
205
+ ' color: ' . $icon_data['color'] . ' !important;' : '';
206
+ echo '<style>.view.' . $slug . '::after { font-family: WooCommerce !important;' . $color_style .
207
+ ' content: "\\' . $icon_data['content'] . '" !important; }</style>';
208
+ }
 
209
  }
210
 
211
  /**
212
  * add_custom_order_statuses_to_reports.
213
  *
214
+ * @version 3.2.2
215
  */
216
  function add_custom_order_statuses_to_reports( $order_statuses ) {
217
  if ( is_array( $order_statuses ) && in_array( 'completed', $order_statuses ) ) {
218
+ return array_merge( $order_statuses, array_keys( $this->get_custom_order_statuses( true ) ) );
219
+ } else {
220
+ return $order_statuses;
 
 
 
221
  }
 
222
  }
223
 
224
  /**
225
  * set_default_order_status.
226
+ *
227
+ * @version 3.2.2
228
  */
229
+ function set_default_order_status( $status ) {
230
+ return ( 'wcj_no_changes' != ( $default_status = get_option( 'wcj_orders_custom_statuses_default_status', 'pending' ) ) ? $default_status : $status );
231
  }
232
 
233
  /**
234
  * register_custom_post_statuses.
235
+ *
236
+ * @version 3.2.2
237
  */
238
  function register_custom_post_statuses() {
239
+ $custom_statuses = $this->get_custom_order_statuses();
240
+ foreach ( $custom_statuses as $slug => $label )
241
  register_post_status( $slug, array(
242
  'label' => $label,
243
  'public' => true,
251
 
252
  /**
253
  * add_custom_statuses_to_filter.
254
+ *
255
+ * @version 3.2.2
256
  */
257
  function add_custom_statuses_to_filter( $order_statuses ) {
258
+ return array_merge( ( '' == $order_statuses ? array() : $order_statuses ), $this->get_custom_order_statuses() );
 
 
259
  }
260
 
261
  /**
262
  * hook_statuses_icons_css.
263
  *
264
+ * @verison 3.2.2
265
  */
266
  function hook_statuses_icons_css() {
267
+ $output = '';
268
+ $statuses = $this->get_custom_order_statuses( true );
 
269
  foreach( $statuses as $status => $status_name ) {
270
+ $icon_data = $this->get_status_icon_data( $status );
271
+ $output .= 'mark.' . $status . '::after { content: "\\' . $icon_data['content'] . '"; color: ' . $icon_data['color'] . '; }';
272
+ $output .= 'mark.' . $status . ':after {font-family:WooCommerce;speak:none;font-weight:400;font-variant:normal;text-transform:none;' .
273
+ 'line-height:1;-webkit-font-smoothing:antialiased;margin:0;text-indent:0;position:absolute;top:0;left:0;width:100%;height:100%;text-align:center}';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  }
275
+ if ( '' != $output ) {
276
+ echo '<style>' . $output . '</style>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  }
278
  }
279
 
280
  /**
281
  * create_custom_statuses_tool.
282
  *
283
+ * @version 3.2.2
 
 
 
284
  */
285
  function create_custom_statuses_tool() {
286
+ return $this->custom_statuses_tool->create_tool();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
  }
288
 
289
  /**
291
  *
292
  * Using Javascript until WordPress core fixes: http://core.trac.wordpress.org/ticket/16031
293
  *
294
+ * @version 3.2.2
295
  * @since 2.2.7
296
  */
297
  function bulk_admin_footer() {
298
  global $post_type;
299
  if ( 'shop_order' == $post_type ) {
300
  ?><script type="text/javascript"><?php
301
+ foreach( wcj_get_order_statuses() as $key => $order_status ) {
302
  if ( in_array( $key, array( 'processing', 'on-hold', 'completed', ) ) ) continue;
303
  ?>jQuery(function() {
304
+ jQuery('<option>').val('mark_<?php echo $key; ?>').text('<?php echo __( 'Mark', 'woocommerce-jetpack' ) . ' ' .
305
+ $order_status; ?>').appendTo('select[name="action"]');
306
+ jQuery('<option>').val('mark_<?php echo $key; ?>').text('<?php echo __( 'Mark', 'woocommerce-jetpack' ) . ' ' .
307
+ $order_status; ?>').appendTo('select[name="action2"]');
308
  });<?php
309
  }
310
  ?></script><?php
311
  }
312
  }
313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  }
315
 
316
  endif;
includes/class-wcj-order-quantities.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Order Min/Max Quantities
4
  *
5
- * @version 2.9.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,11 +16,12 @@ class WCJ_Order_Quantities extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 2.9.0
20
  * @since 2.9.0
21
- * @todo quantities per item - per product
22
- * @todo (maybe) do not allow to add/remove items (instead of just printing messages)
23
  * @todo (maybe) order quantities by user roles
 
24
  */
25
  function __construct() {
26
 
@@ -37,7 +38,120 @@ class WCJ_Order_Quantities extends WCJ_Module {
37
  if ( 'yes' === get_option( 'wcj_order_quantities_stop_from_seeing_checkout', 'no' ) ) {
38
  add_action( 'wp', array( $this, 'stop_from_seeing_checkout' ), PHP_INT_MAX );
39
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
42
  }
43
 
@@ -134,7 +248,7 @@ class WCJ_Order_Quantities extends WCJ_Module {
134
  /**
135
  * check_quantities.
136
  *
137
- * @version 2.9.0
138
  * @since 2.9.0
139
  */
140
  function check_quantities( $min_or_max, $cart_item_quantities, $cart_total_quantity, $_is_cart, $_return ) {
@@ -150,8 +264,30 @@ class WCJ_Order_Quantities extends WCJ_Module {
150
  }
151
  }
152
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  if ( 0 != ( $max_or_max_per_item_quantity = apply_filters( 'booster_get_option', 0, get_option( 'wcj_order_quantities_' . $min_or_max . '_per_item_quantity', 0 ) ) ) ) {
154
  foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
 
 
 
 
 
 
155
  if (
156
  ( 'max' === $min_or_max && $cart_item_quantity > $max_or_max_per_item_quantity ) ||
157
  ( 'min' === $min_or_max && $cart_item_quantity < $max_or_max_per_item_quantity )
2
  /**
3
  * Booster for WooCommerce - Module - Order Min/Max Quantities
4
  *
5
+ * @version 3.2.2
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.2.2
20
  * @since 2.9.0
21
+ * @todo for cart: `apply_filters( 'woocommerce_quantity_input_args', wp_parse_args( $args, $defaults ), $product );`
22
+ * @todo loop (`woocommerce_loop_add_to_cart_link`)
23
  * @todo (maybe) order quantities by user roles
24
+ * @todo (maybe) `woocommerce_quantity_input_step`
25
  */
26
  function __construct() {
27
 
38
  if ( 'yes' === get_option( 'wcj_order_quantities_stop_from_seeing_checkout', 'no' ) ) {
39
  add_action( 'wp', array( $this, 'stop_from_seeing_checkout' ), PHP_INT_MAX );
40
  }
41
+ if (
42
+ 'yes' === apply_filters( 'booster_get_option', 'no', get_option( 'wcj_order_quantities_min_per_item_quantity_per_product', 'no' ) ) ||
43
+ 'yes' === apply_filters( 'booster_get_option', 'no', get_option( 'wcj_order_quantities_max_per_item_quantity_per_product', 'no' ) )
44
+ ) {
45
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
46
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
47
+ }
48
+ add_filter( 'woocommerce_available_variation', array( $this, 'set_quantity_input_min_max_variation' ), PHP_INT_MAX, 3 );
49
+ if ( 'yes' === get_option( 'wcj_order_quantities_min_section_enabled', 'no' ) ) {
50
+ add_filter( 'woocommerce_quantity_input_min', array( $this, 'set_quantity_input_min' ), PHP_INT_MAX, 2 );
51
+ }
52
+ if ( 'yes' === get_option( 'wcj_order_quantities_max_section_enabled', 'no' ) ) {
53
+ add_filter( 'woocommerce_quantity_input_max', array( $this, 'set_quantity_input_max' ), PHP_INT_MAX, 2 );
54
+ }
55
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_script' ) );
56
+ }
57
+ }
58
+ }
59
+
60
+ /**
61
+ * enqueue_script.
62
+ *
63
+ * @version 3.2.2
64
+ * @since 3.2.2
65
+ * @todo make this optional?
66
+ */
67
+ function enqueue_script() {
68
+ $_product = wc_get_product();
69
+ if ( $_product && $_product->is_type( 'variable' ) ) {
70
+ $product_quantities = array();
71
+ foreach ( $_product->get_available_variations() as $variation ) {
72
+ $product_quantities[ $variation['variation_id'] ] = array(
73
+ 'min_qty' => $variation['min_qty'],
74
+ 'max_qty' => $variation['max_qty'],
75
+ );
76
  }
77
+ wp_enqueue_script( 'wcj-order-quantities', trailingslashit( wcj_plugin_url() ) . 'includes/js/wcj-order-quantities.js', array( 'jquery' ), WCJ()->version, true );
78
+ wp_localize_script( 'wcj-order-quantities', 'product_quantities', $product_quantities );
79
+ }
80
+ }
81
+
82
+ /**
83
+ * get_product_quantity.
84
+ *
85
+ * @version 3.2.2
86
+ * @since 3.2.2
87
+ */
88
+ function get_product_quantity( $min_or_max, $_product, $default_qty ) {
89
+ if ( 'no' === get_option( 'wcj_order_quantities_' . $min_or_max . '_section_enabled', 'no' ) ) {
90
+ return $default_qty;
91
+ }
92
+ if (
93
+ 'yes' === apply_filters( 'booster_get_option', 'no', get_option( 'wcj_order_quantities_' . $min_or_max . '_per_item_quantity_per_product', 'no' ) ) &&
94
+ 0 != ( $max_or_max_per_item_quantity_per_product = get_post_meta( wcj_get_product_id( $_product ), '_' . 'wcj_order_quantities_' . $min_or_max, true ) )
95
+ ) {
96
+ return $max_or_max_per_item_quantity_per_product;
97
+ } elseif ( 0 != ( $max_or_max_per_item_quantity = apply_filters( 'booster_get_option', 0, get_option( 'wcj_order_quantities_' . $min_or_max . '_per_item_quantity', 0 ) ) ) ) {
98
+ return $max_or_max_per_item_quantity;
99
+ } else {
100
+ return $default_qty;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * set_quantity_input_min_max_variation.
106
+ *
107
+ * @version 3.2.2
108
+ * @since 3.2.2
109
+ */
110
+ function set_quantity_input_min_max_variation( $args, $_product, $_variation ) {
111
+ $args['min_qty'] = $this->get_product_quantity( 'min', $_variation, $args['min_qty'] );
112
+ $args['max_qty'] = $this->get_product_quantity( 'max', $_variation, $args['max_qty'] );
113
+ $_max = $_variation->get_max_purchase_quantity();
114
+ if ( -1 != $_max && $args['max_qty'] > $_max ) {
115
+ $args['max_qty'] = $_max;
116
+ }
117
+ if ( $args['min_qty'] < 0 ) {
118
+ $args['min_qty'] = '';
119
+ }
120
+ if ( $args['max_qty'] < 0 ) {
121
+ $args['max_qty'] = '';
122
+ }
123
+ return $args;
124
+ }
125
+
126
+ /**
127
+ * set_quantity_input_min.
128
+ *
129
+ * @version 3.2.2
130
+ * @since 3.2.2
131
+ */
132
+ function set_quantity_input_min( $qty, $_product ) {
133
+ if ( ! $_product->is_type( 'variable' ) ) {
134
+ $min = $this->get_product_quantity( 'min', $_product, $qty );
135
+ $_max = $_product->get_max_purchase_quantity();
136
+ return ( -1 == $_max || $min < $_max ? $min : $_max );
137
+ } else {
138
+ return $qty;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * set_quantity_input_max.
144
+ *
145
+ * @version 3.2.2
146
+ * @since 3.2.2
147
+ */
148
+ function set_quantity_input_max( $qty, $_product ) {
149
+ if ( ! $_product->is_type( 'variable' ) ) {
150
+ $max = $this->get_product_quantity( 'max', $_product, $qty );
151
+ $_max = $_product->get_max_purchase_quantity();
152
+ return ( -1 == $_max || $max < $_max ? $max : $_max );
153
+ } else {
154
+ return $qty;
155
  }
156
  }
157
 
248
  /**
249
  * check_quantities.
250
  *
251
+ * @version 3.2.2
252
  * @since 2.9.0
253
  */
254
  function check_quantities( $min_or_max, $cart_item_quantities, $cart_total_quantity, $_is_cart, $_return ) {
264
  }
265
  }
266
  }
267
+ if ( apply_filters( 'booster_get_option', 'no', get_option( 'wcj_order_quantities_' . $min_or_max . '_per_item_quantity_per_product', 'no' ) ) ) {
268
+ foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
269
+ if ( 0 != ( $max_or_max_per_item_quantity = get_post_meta( $_product_id, '_' . 'wcj_order_quantities_' . $min_or_max, true ) ) ) {
270
+ if (
271
+ ( 'max' === $min_or_max && $cart_item_quantity > $max_or_max_per_item_quantity ) ||
272
+ ( 'min' === $min_or_max && $cart_item_quantity < $max_or_max_per_item_quantity )
273
+ ) {
274
+ if ( $_return ) {
275
+ return false;
276
+ } else {
277
+ $this->print_message( $min_or_max . '_per_item_quantity', $_is_cart, $max_or_max_per_item_quantity, $cart_item_quantity, $_product_id );
278
+ }
279
+ }
280
+ }
281
+ }
282
+ }
283
  if ( 0 != ( $max_or_max_per_item_quantity = apply_filters( 'booster_get_option', 0, get_option( 'wcj_order_quantities_' . $min_or_max . '_per_item_quantity', 0 ) ) ) ) {
284
  foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
285
+ if (
286
+ 'yes' === apply_filters( 'booster_get_option', 'no', get_option( 'wcj_order_quantities_' . $min_or_max . '_per_item_quantity_per_product', 'no' ) ) &&
287
+ 0 != get_post_meta( $_product_id, '_' . 'wcj_order_quantities_' . $min_or_max, true )
288
+ ) {
289
+ continue;
290
+ }
291
  if (
292
  ( 'max' === $min_or_max && $cart_item_quantity > $max_or_max_per_item_quantity ) ||
293
  ( 'min' === $min_or_max && $cart_item_quantity < $max_or_max_per_item_quantity )
includes/class-wcj-payment-gateways-by-user-role.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Gateways by User Role
4
  *
5
- * @version 3.0.0
6
  * @since 2.5.3
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Payment_Gateways_By_User_Role extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 2.8.0
20
  * @since 2.5.3
21
  */
22
  function __construct() {
@@ -28,7 +28,7 @@ class WCJ_Payment_Gateways_By_User_Role extends WCJ_Module {
28
  parent::__construct();
29
 
30
  if ( $this->is_enabled() ) {
31
- add_filter( 'woocommerce_available_payment_gateways', array( $this, 'available_payment_gateways' ), PHP_INT_MAX, 1 );
32
  }
33
  }
34
 
2
  /**
3
  * Booster for WooCommerce - Module - Gateways by User Role
4
  *
5
+ * @version 3.2.2
6
  * @since 2.5.3
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.2.2
20
  * @since 2.5.3
21
  */
22
  function __construct() {
28
  parent::__construct();
29
 
30
  if ( $this->is_enabled() ) {
31
+ add_filter( 'woocommerce_available_payment_gateways', array( $this, 'available_payment_gateways' ), PHP_INT_MAX - 100, 1 );
32
  }
33
  }
34
 
includes/class-wcj-price-by-user-role.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Price by User Role
4
  *
5
- * @version 3.2.0
6
  * @since 2.5.0
7
  * @author Algoritmika Ltd.
8
  * @todo Fix "Make Empty Price" option for variable products
@@ -17,7 +17,7 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 3.2.0
21
  * @since 2.5.0
22
  */
23
  function __construct() {
@@ -29,13 +29,14 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
29
  parent::__construct();
30
 
31
  if ( $this->is_enabled() ) {
 
32
  if ( 'yes' === get_option( 'wcj_price_by_user_role_per_product_enabled', 'yes' ) ) {
33
  add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
34
  add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
35
  }
36
  if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
37
  if ( 'no' === get_option( 'wcj_price_by_user_role_for_bots_disabled', 'no' ) || ! wcj_is_bot() ) {
38
- wcj_add_change_price_hooks( $this, PHP_INT_MAX - 200 );
39
  if ( ( $this->disable_for_regular_price = ( 'yes' === get_option( 'wcj_price_by_user_role_disable_for_regular_price', 'no' ) ) ) ) {
40
  add_filter( 'woocommerce_product_is_on_sale', array( $this, 'maybe_make_on_sale' ), PHP_INT_MAX, 2 );
41
  }
@@ -158,7 +159,7 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
158
  /**
159
  * change_price.
160
  *
161
- * @version 3.2.0
162
  * @since 2.5.0
163
  */
164
  function change_price( $price, $_product ) {
@@ -219,12 +220,12 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
219
 
220
  // Maybe disable for products on sale
221
  if ( 'yes' === get_option( 'wcj_price_by_user_role_disable_for_products_on_sale', 'no' ) ) {
222
- wcj_remove_change_price_hooks( $this, PHP_INT_MAX - 200 );
223
  if ( $_product && $_product->is_on_sale() ) {
224
- wcj_add_change_price_hooks( $this, PHP_INT_MAX - 200 );
225
  return $price;
226
  } else {
227
- wcj_add_change_price_hooks( $this, PHP_INT_MAX - 200 );
228
  }
229
  }
230
 
2
  /**
3
  * Booster for WooCommerce - Module - Price by User Role
4
  *
5
+ * @version 3.2.2
6
  * @since 2.5.0
7
  * @author Algoritmika Ltd.
8
  * @todo Fix "Make Empty Price" option for variable products
17
  /**
18
  * Constructor.
19
  *
20
+ * @version 3.2.2
21
  * @since 2.5.0
22
  */
23
  function __construct() {
29
  parent::__construct();
30
 
31
  if ( $this->is_enabled() ) {
32
+ $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'price_by_user_role' );
33
  if ( 'yes' === get_option( 'wcj_price_by_user_role_per_product_enabled', 'yes' ) ) {
34
  add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
35
  add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
36
  }
37
  if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
38
  if ( 'no' === get_option( 'wcj_price_by_user_role_for_bots_disabled', 'no' ) || ! wcj_is_bot() ) {
39
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority );
40
  if ( ( $this->disable_for_regular_price = ( 'yes' === get_option( 'wcj_price_by_user_role_disable_for_regular_price', 'no' ) ) ) ) {
41
  add_filter( 'woocommerce_product_is_on_sale', array( $this, 'maybe_make_on_sale' ), PHP_INT_MAX, 2 );
42
  }
159
  /**
160
  * change_price.
161
  *
162
+ * @version 3.2.2
163
  * @since 2.5.0
164
  */
165
  function change_price( $price, $_product ) {
220
 
221
  // Maybe disable for products on sale
222
  if ( 'yes' === get_option( 'wcj_price_by_user_role_disable_for_products_on_sale', 'no' ) ) {
223
+ wcj_remove_change_price_hooks( $this, $this->price_hooks_priority );
224
  if ( $_product && $_product->is_on_sale() ) {
225
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority );
226
  return $price;
227
  } else {
228
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority );
229
  }
230
  }
231
 
includes/class-wcj-product-addons.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Product Addons
4
  *
5
- * @version 3.0.0
6
  * @since 2.5.3
7
  * @author Algoritmika Ltd.
8
  * @todo admin order view (names);
@@ -126,14 +126,14 @@ class WCJ_Product_Addons extends WCJ_Module {
126
  if ( WCJ()->modules['multicurrency']->is_enabled() ) {
127
  return WCJ()->modules['multicurrency']->change_price( $price, null );
128
  }
129
- // No cnahges
130
  return $price;
131
  }
132
 
133
  /**
134
  * price_change_ajax.
135
  *
136
- * @version 3.0.0
137
  * @since 2.5.3
138
  */
139
  function price_change_ajax( $param ) {
@@ -146,7 +146,7 @@ class WCJ_Product_Addons extends WCJ_Module {
146
  $the_addons_price = 0;
147
  foreach ( $addons as $addon ) {
148
  if ( isset( $_POST[ $addon['checkbox_key'] ] ) ) {
149
- if ( 'checkbox' === $addon['type'] || '' == $addon['type'] ) {
150
  $the_addons_price += $addon['price_value'];
151
  } elseif ( 'radio' === $addon['type'] || 'select' === $addon['type'] ) {
152
  $labels = explode( PHP_EOL, $addon['label_value'] );
@@ -215,6 +215,7 @@ class WCJ_Product_Addons extends WCJ_Module {
215
  *
216
  * @version 3.0.0
217
  * @since 2.5.3
 
218
  */
219
  function get_product_addons( $product_id ) {
220
  $addons = array();
@@ -382,16 +383,19 @@ class WCJ_Product_Addons extends WCJ_Module {
382
  /**
383
  * add_addons_price_to_cart_item_data.
384
  *
385
- * @version 3.0.0
386
  * @since 2.5.3
387
  */
388
  function add_addons_price_to_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
389
  $addons = $this->get_product_addons( $product_id );
390
  foreach ( $addons as $addon ) {
391
  if ( isset( $_POST[ $addon['checkbox_key'] ] ) ) {
392
- if ( 'checkbox' === $addon['type'] || '' == $addon['type'] ) {
393
  $cart_item_data[ $addon['price_key'] ] = $addon['price_value'];
394
  $cart_item_data[ $addon['label_key'] ] = $addon['label_value'];
 
 
 
395
  } elseif ( 'radio' === $addon['type'] || 'select' === $addon['type'] ) {
396
  $prices = explode( PHP_EOL, $addon['price_value'] );
397
  $labels = explode( PHP_EOL, $addon['label_value'] );
@@ -413,7 +417,7 @@ class WCJ_Product_Addons extends WCJ_Module {
413
  /**
414
  * add_addons_to_frontend.
415
  *
416
- * @version 3.0.0
417
  * @since 2.5.3
418
  */
419
  function add_addons_to_frontend() {
@@ -440,6 +444,16 @@ class WCJ_Product_Addons extends WCJ_Module {
440
  '<label for="' . $addon['checkbox_key'] . '">' . $addon['label_value'] . ' ('. wc_price( wcj_get_product_display_price( $_product, $this->maybe_convert_currency( $addon['price_value'] ) ) ) . ')' . '</label>' .
441
  $maybe_tooltip .
442
  '</p>';
 
 
 
 
 
 
 
 
 
 
443
  } elseif ( 'radio' === $addon['type'] || 'select' === $addon['type'] ) {
444
  $prices = explode( PHP_EOL, $addon['price_value'] );
445
  $labels = explode( PHP_EOL, $addon['label_value'] );
2
  /**
3
  * Booster for WooCommerce - Module - Product Addons
4
  *
5
+ * @version 3.2.2
6
  * @since 2.5.3
7
  * @author Algoritmika Ltd.
8
  * @todo admin order view (names);
126
  if ( WCJ()->modules['multicurrency']->is_enabled() ) {
127
  return WCJ()->modules['multicurrency']->change_price( $price, null );
128
  }
129
+ // No changes
130
  return $price;
131
  }
132
 
133
  /**
134
  * price_change_ajax.
135
  *
136
+ * @version 3.2.2
137
  * @since 2.5.3
138
  */
139
  function price_change_ajax( $param ) {
146
  $the_addons_price = 0;
147
  foreach ( $addons as $addon ) {
148
  if ( isset( $_POST[ $addon['checkbox_key'] ] ) ) {
149
+ if ( ( 'checkbox' === $addon['type'] || '' == $addon['type'] ) || ( 'text' == $addon['type'] && '' != $_POST[ $addon['checkbox_key'] ] ) ) {
150
  $the_addons_price += $addon['price_value'];
151
  } elseif ( 'radio' === $addon['type'] || 'select' === $addon['type'] ) {
152
  $labels = explode( PHP_EOL, $addon['label_value'] );
215
  *
216
  * @version 3.0.0
217
  * @since 2.5.3
218
+ * @todo (maybe) `checkbox_key` is mislabelled, should be `key` (or maybe `value_key`)
219
  */
220
  function get_product_addons( $product_id ) {
221
  $addons = array();
383
  /**
384
  * add_addons_price_to_cart_item_data.
385
  *
386
+ * @version 3.2.2
387
  * @since 2.5.3
388
  */
389
  function add_addons_price_to_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
390
  $addons = $this->get_product_addons( $product_id );
391
  foreach ( $addons as $addon ) {
392
  if ( isset( $_POST[ $addon['checkbox_key'] ] ) ) {
393
+ if ( ( 'checkbox' === $addon['type'] || '' == $addon['type'] ) || ( 'text' == $addon['type'] && '' != $_POST[ $addon['checkbox_key'] ] ) ) {
394
  $cart_item_data[ $addon['price_key'] ] = $addon['price_value'];
395
  $cart_item_data[ $addon['label_key'] ] = $addon['label_value'];
396
+ if ( 'text' == $addon['type'] ) {
397
+ $cart_item_data[ $addon['label_key'] ] .= ' (' . $_POST[ $addon['checkbox_key'] ] . ')';
398
+ }
399
  } elseif ( 'radio' === $addon['type'] || 'select' === $addon['type'] ) {
400
  $prices = explode( PHP_EOL, $addon['price_value'] );
401
  $labels = explode( PHP_EOL, $addon['label_value'] );
417
  /**
418
  * add_addons_to_frontend.
419
  *
420
+ * @version 3.2.2
421
  * @since 2.5.3
422
  */
423
  function add_addons_to_frontend() {
444
  '<label for="' . $addon['checkbox_key'] . '">' . $addon['label_value'] . ' ('. wc_price( wcj_get_product_display_price( $_product, $this->maybe_convert_currency( $addon['price_value'] ) ) ) . ')' . '</label>' .
445
  $maybe_tooltip .
446
  '</p>';
447
+ } elseif ( 'text' == $addon['type'] ) {
448
+ $default_value = ( isset( $_POST[ $addon['checkbox_key'] ] ) ? $_POST[ $addon['checkbox_key'] ] : $addon['default'] );
449
+ $maybe_tooltip = ( '' != $addon['tooltip'] ) ?
450
+ ' <img style="display:inline;" class="wcj-question-icon" src="' . wcj_plugin_url() . '/assets/images/question-icon.png' . '" title="' . $addon['tooltip'] . '">' :
451
+ '';
452
+ $html .= '<p>' .
453
+ '<label for="' . $addon['checkbox_key'] . '">' . $addon['label_value'] . ' ('. wc_price( wcj_get_product_display_price( $_product, $this->maybe_convert_currency( $addon['price_value'] ) ) ) . ')' . '</label>' . ' ' .
454
+ '<input type="text" id="' . $addon['checkbox_key'] . '" name="' . $addon['checkbox_key'] . '" placeholder="' . $addon['placeholder'] . '" value="' . $default_value . '"' . $is_required . '>' .
455
+ $maybe_tooltip .
456
+ '</p>';
457
  } elseif ( 'radio' === $addon['type'] || 'select' === $addon['type'] ) {
458
  $prices = explode( PHP_EOL, $addon['price_value'] );
459
  $labels = explode( PHP_EOL, $addon['label_value'] );
includes/classes/class-wcj-invoice.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce Invoice
4
  *
5
- * @version 3.1.1
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -27,20 +27,18 @@ class WCJ_Invoice {
27
  * is_created.
28
  */
29
  function is_created() {
30
- return ( '' != get_post_meta( $this->order_id, '_wcj_invoicing_' . $this->invoice_type . '_date', true ) ) ? true : false;
31
  }
32
 
33
  /**
34
  * delete.
35
  *
36
- * @version 2.3.0
37
  */
38
  function delete() {
39
  update_post_meta( $this->order_id, '_wcj_invoicing_' . $this->invoice_type . '_number_id', 0 );
40
- //update_post_meta( $this->order_id, '_wcj_invoicing_' . $this->invoice_type . '_number', 0 );
41
  update_post_meta( $this->order_id, '_wcj_invoicing_' . $this->invoice_type . '_date', '' );
42
-
43
- if ( 'yes' === get_option( 'wcj_invoicing_' . $this->invoice_type . '_sequential_enabled' ) ) {
44
  $option_name = 'wcj_invoicing_' . $this->invoice_type . '_numbering_counter';
45
  $the_invoice_counter = get_option( $option_name, 1 );
46
  update_option( $option_name, ( $the_invoice_counter - 1 ) );
@@ -50,7 +48,7 @@ class WCJ_Invoice {
50
  /**
51
  * create.
52
  *
53
- * @version 3.1.1
54
  * @todo use mysql transaction enabled (as in "wcj_order_number_use_mysql_transaction_enabled")
55
  */
56
  function create( $date = '' ) {
@@ -62,18 +60,15 @@ class WCJ_Invoice {
62
  return;
63
  }
64
  }
65
- //if ( '' == get_post_meta( $order_id, '_wcj_invoicing_' . $invoice_type . '_number', true ) ) {
66
- if ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type . '_sequential_enabled' ) ) {
67
- $the_invoice_number = get_option( 'wcj_invoicing_' . $invoice_type . '_numbering_counter', 1 );
68
- update_option( 'wcj_invoicing_' . $invoice_type . '_numbering_counter', ( $the_invoice_number + 1 ) );
69
- } else {
70
- $the_invoice_number = $order_id;
71
- }
72
- $the_date = ( '' == $date ) ? current_time( 'timestamp' ) : $date;
73
- update_post_meta( $order_id, '_wcj_invoicing_' . $invoice_type . '_number_id', $the_invoice_number );
74
- // update_post_meta( $order_id, '_wcj_invoicing_' . $invoice_type . '_number', $this->get_invoice_full_number( $the_invoice_number ) );
75
- update_post_meta( $order_id, '_wcj_invoicing_' . $invoice_type . '_date', $the_date );
76
- //}
77
  }
78
 
79
  /**
@@ -96,32 +91,23 @@ class WCJ_Invoice {
96
 
97
  /**
98
  * get_invoice_number.
 
 
99
  */
100
  function get_invoice_number() {
101
- //$the_number = get_post_meta( $this->order_id, '_wcj_invoicing_' . $this->invoice_type . '_number', true );
102
- $the_number_id = get_post_meta( $this->order_id, '_wcj_invoicing_' . $this->invoice_type . '_number_id', true );
103
- //$the_number = $this->get_invoice_full_number( $the_number_id );
104
- $the_prefix = get_option( 'wcj_invoicing_' . $this->invoice_type . '_numbering_prefix' );
105
- $the_suffix = get_option( 'wcj_invoicing_' . $this->invoice_type . '_numbering_suffix' );
106
- $the_number = do_shortcode( sprintf( '%s%0' . get_option( 'wcj_invoicing_' . $this->invoice_type . '_numbering_counter_width', 0 ). 'd%s',
107
- $the_prefix,
108
- $the_number_id,
109
- $the_suffix ) );
110
- return apply_filters( 'wcj_get_' . $this->invoice_type . '_number', $the_number, $this->order_id );
 
111
  }
112
 
113
- /**
114
- * get_invoice_full_number.
115
- *
116
- private function get_invoice_full_number( $the_number ) {
117
- $the_prefix = get_option( 'wcj_invoicing_' . $this->invoice_type . '_numbering_prefix' );
118
- $the_suffix = get_option( 'wcj_invoicing_' . $this->invoice_type . '_numbering_suffix' );
119
- return do_shortcode( sprintf( '%s%0' . get_option( 'wcj_invoicing_' . $this->invoice_type . '_numbering_counter_width', 0 ). 'd%s',
120
- $the_prefix,
121
- $the_number,
122
- $the_suffix ) );
123
- }
124
- /**/
125
  }
126
 
127
  endif;
2
  /**
3
  * Booster for WooCommerce Invoice
4
  *
5
+ * @version 3.2.2
6
  * @author Algoritmika Ltd.
7
  */
8
 
27
  * is_created.
28
  */
29
  function is_created() {
30
+ return ( '' != get_post_meta( $this->order_id, '_wcj_invoicing_' . $this->invoice_type . '_date', true ) );
31
  }
32
 
33
  /**
34
  * delete.
35
  *
36
+ * @version 3.2.2
37
  */
38
  function delete() {
39
  update_post_meta( $this->order_id, '_wcj_invoicing_' . $this->invoice_type . '_number_id', 0 );
 
40
  update_post_meta( $this->order_id, '_wcj_invoicing_' . $this->invoice_type . '_date', '' );
41
+ if ( 'yes' === get_option( 'wcj_invoicing_' . $this->invoice_type . '_sequential_enabled', 'no' ) ) {
 
42
  $option_name = 'wcj_invoicing_' . $this->invoice_type . '_numbering_counter';
43
  $the_invoice_counter = get_option( $option_name, 1 );
44
  update_option( $option_name, ( $the_invoice_counter - 1 ) );
48
  /**
49
  * create.
50
  *
51
+ * @version 3.2.2
52
  * @todo use mysql transaction enabled (as in "wcj_order_number_use_mysql_transaction_enabled")
53
  */
54
  function create( $date = '' ) {
60
  return;
61
  }
62
  }
63
+ if ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type . '_sequential_enabled', 'no' ) ) {
64
+ $the_invoice_number = get_option( 'wcj_invoicing_' . $invoice_type . '_numbering_counter', 1 );
65
+ update_option( 'wcj_invoicing_' . $invoice_type . '_numbering_counter', ( $the_invoice_number + 1 ) );
66
+ } else {
67
+ $the_invoice_number = $order_id;
68
+ }
69
+ $the_date = ( '' == $date ) ? current_time( 'timestamp' ) : $date;
70
+ update_post_meta( $order_id, '_wcj_invoicing_' . $invoice_type . '_number_id', $the_invoice_number );
71
+ update_post_meta( $order_id, '_wcj_invoicing_' . $invoice_type . '_date', $the_date );
 
 
 
72
  }
73
 
74
  /**
91
 
92
  /**
93
  * get_invoice_number.
94
+ *
95
+ * @version 3.2.2
96
  */
97
  function get_invoice_number() {
98
+ $replaced_values = array(
99
+ '%prefix%' => get_option( 'wcj_invoicing_' . $this->invoice_type . '_numbering_prefix', '' ),
100
+ '%counter%' => sprintf( '%0' . get_option( 'wcj_invoicing_' . $this->invoice_type . '_numbering_counter_width', 0 ) . 'd',
101
+ get_post_meta( $this->order_id, '_wcj_invoicing_' . $this->invoice_type . '_number_id', true ) ),
102
+ '%suffix%' => get_option( 'wcj_invoicing_' . $this->invoice_type . '_numbering_suffix', '' ),
103
+ );
104
+ return apply_filters( 'wcj_get_' . $this->invoice_type . '_number',
105
+ do_shortcode( str_replace( array_keys( $replaced_values ), $replaced_values,
106
+ get_option( 'wcj_invoicing_' . $this->invoice_type . '_numbering_template', '%prefix%%counter%%suffix%' ) ) ),
107
+ $this->order_id
108
+ );
109
  }
110
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
112
 
113
  endif;
includes/classes/class-wcj-product.php DELETED
@@ -1,58 +0,0 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce Product
4
- *
5
- * @version 2.4.8
6
- * @since 2.2.0
7
- * @author Algoritmika Ltd.
8
- */
9
-
10
- if ( ! defined( 'ABSPATH' ) ) exit;
11
-
12
- if ( ! class_exists( 'WCJ_Product' ) ) :
13
-
14
- class WCJ_Product {
15
-
16
- public $id;
17
- public $product;
18
-
19
- /**
20
- * Constructor.
21
- */
22
- function __construct( $product_id ) {
23
- $this->id = $product_id;
24
- // $this->product = wc_get_product( $this->id );
25
- }
26
-
27
- /**
28
- * get_purchase_price.
29
- *
30
- * @version 2.4.8
31
- */
32
- function get_purchase_price() {
33
- $purchase_price = 0;
34
- if ( 'yes' === get_option( 'wcj_purchase_price_enabled', 'yes' ) ) {
35
- $purchase_price += get_post_meta( $this->id, '_' . 'wcj_purchase_price' , true );
36
- }
37
- if ( 'yes' === get_option( 'wcj_purchase_price_extra_enabled', 'yes' ) ) {
38
- $purchase_price += get_post_meta( $this->id, '_' . 'wcj_purchase_price_extra', true );
39
- }
40
- if ( 'yes' === get_option( 'wcj_purchase_price_affiliate_commission_enabled', 'no' ) ) {
41
- $purchase_price += get_post_meta( $this->id, '_' . 'wcj_purchase_price_affiliate_commission', true );
42
- }
43
- $total_number = apply_filters( 'booster_get_option', 1, get_option( 'wcj_purchase_data_custom_price_fields_total_number', 1 ) );
44
- for ( $i = 1; $i <= $total_number; $i++ ) {
45
- if ( '' == get_option( 'wcj_purchase_data_custom_price_field_name_' . $i, '' ) ) {
46
- continue;
47
- }
48
- $meta_value = get_post_meta( $this->id, '_' . 'wcj_purchase_price_custom_field_' . $i, true );
49
- if ( '' != $meta_value ) {
50
- $the_type = get_option( 'wcj_purchase_data_custom_price_field_type_' . $i, 'fixed' );
51
- $purchase_price += ( 'fixed' === $the_type ) ? $meta_value : $purchase_price * $meta_value / 100.0;
52
- }
53
- }
54
- return apply_filters( 'wcj_get_product_purchase_price', $purchase_price, $this->id );
55
- }
56
- }
57
-
58
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/emails/class-wc-email-wcj-custom.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * An email sent to recipient list when selected triggers are called.
6
  *
7
- * @version 3.1.2
8
  * @since 2.3.9
9
  * @author Algoritmika Ltd.
10
  * @extends WC_Email
@@ -104,7 +104,7 @@ class WC_Email_WCJ_Custom extends WC_Email {
104
  /**
105
  * trigger.
106
  *
107
- * @version 3.1.2
108
  */
109
  function trigger( $order_id ) {
110
 
@@ -134,7 +134,7 @@ class WC_Email_WCJ_Custom extends WC_Email {
134
  foreach ( $trigger_hooks as $trigger_hook ) {
135
  if ( false !== ( $pos = strpos( $trigger_hook, 'woocommerce_new_order_notification' ) ) ) {
136
  $the_status = 'wc-' . substr( $trigger_hook, 35 );
137
- if ( 'wc-wcj_any_status' === $the_status || $this->object->post_status === $the_status ) {
138
  $is_status_found = true;
139
  break;
140
  }
@@ -209,7 +209,7 @@ class WC_Email_WCJ_Custom extends WC_Email {
209
  $status_change_triggers = array();
210
  $new_order_triggers = array();
211
  $status_triggers = array();
212
- $order_statuses = wcj_get_order_statuses_v2();
213
  foreach ( $order_statuses as $slug => $name ) {
214
  $new_order_triggers[ 'woocommerce_new_order_notification_' . $slug ] = sprintf( __( 'New order (%s)', 'woocommerce-jetpack' ), $name );
215
  $status_triggers[ 'woocommerce_order_status_' . $slug . '_notification' ] = sprintf( __( 'Order status updated to %s', 'woocommerce-jetpack' ), $name );
4
  *
5
  * An email sent to recipient list when selected triggers are called.
6
  *
7
+ * @version 3.2.2
8
  * @since 2.3.9
9
  * @author Algoritmika Ltd.
10
  * @extends WC_Email
104
  /**
105
  * trigger.
106
  *
107
+ * @version 3.2.2
108
  */
109
  function trigger( $order_id ) {
110
 
134
  foreach ( $trigger_hooks as $trigger_hook ) {
135
  if ( false !== ( $pos = strpos( $trigger_hook, 'woocommerce_new_order_notification' ) ) ) {
136
  $the_status = 'wc-' . substr( $trigger_hook, 35 );
137
+ if ( 'wc-wcj_any_status' === $the_status || wcj_get_order_status( $this->object ) === $the_status ) {
138
  $is_status_found = true;
139
  break;
140
  }
209
  $status_change_triggers = array();
210
  $new_order_triggers = array();
211
  $status_triggers = array();
212
+ $order_statuses = wcj_get_order_statuses();
213
  foreach ( $order_statuses as $slug => $name ) {
214
  $new_order_triggers[ 'woocommerce_new_order_notification_' . $slug ] = sprintf( __( 'New order (%s)', 'woocommerce-jetpack' ), $name );
215
  $status_triggers[ 'woocommerce_order_status_' . $slug . '_notification' ] = sprintf( __( 'Order status updated to %s', 'woocommerce-jetpack' ), $name );
includes/exchange-rates/class-wcj-exchange-rates.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce Exchange Rates
4
  *
5
- * @version 2.9.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -14,6 +14,8 @@ class WCJ_Exchange_Rates {
14
 
15
  /**
16
  * Constructor.
 
 
17
  */
18
  function __construct() {
19
 
@@ -21,6 +23,20 @@ class WCJ_Exchange_Rates {
21
  add_action( 'admin_init', array( $this, 'register_script' ) );
22
 
23
  add_action( 'woocommerce_admin_field_exchange_rate', array( $this, 'output_settings_button' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  }
25
 
26
  /**
@@ -50,10 +66,10 @@ class WCJ_Exchange_Rates {
50
  /**
51
  * enqueue_exchange_rates_script.
52
  *
53
- * @version 2.6.0
54
  */
55
  function enqueue_exchange_rates_script() {
56
- if (
57
  isset( $_GET['section'] ) &&
58
  in_array( $_GET['section'], array(
59
  'multicurrency',
@@ -66,6 +82,17 @@ class WCJ_Exchange_Rates {
66
  ) {
67
  wp_enqueue_script( 'wcj-exchange-rates-ajax' );
68
  }
 
 
 
 
 
 
 
 
 
 
 
69
  }
70
 
71
  /**
2
  /**
3
  * Booster for WooCommerce Exchange Rates
4
  *
5
+ * @version 3.2.2
6
  * @author Algoritmika Ltd.
7
  */
8
 
14
 
15
  /**
16
  * Constructor.
17
+ *
18
+ * @version 3.2.2
19
  */
20
  function __construct() {
21
 
23
  add_action( 'admin_init', array( $this, 'register_script' ) );
24
 
25
  add_action( 'woocommerce_admin_field_exchange_rate', array( $this, 'output_settings_button' ) );
26
+
27
+ add_action( 'wp_ajax_' . 'wcj_ajax_get_exchange_rates_average', array( $this, 'wcj_ajax_get_exchange_rates_average' ) );
28
+ add_action( 'wp_ajax_nopriv_' . 'wcj_ajax_get_exchange_rates_average', array( $this, 'wcj_ajax_get_exchange_rates_average' ) );
29
+ }
30
+
31
+ /**
32
+ * wcj_ajax_get_exchange_rates_average.
33
+ *
34
+ * @version 3.2.2
35
+ * @since 3.2.2
36
+ */
37
+ function wcj_ajax_get_exchange_rates_average() {
38
+ echo wcj_fixer_io_get_exchange_rate_average( $_POST['wcj_currency_from'], $_POST['wcj_currency_to'], $_POST['wcj_start_date'], $_POST['wcj_end_date'] );
39
+ die();
40
  }
41
 
42
  /**
66
  /**
67
  * enqueue_exchange_rates_script.
68
  *
69
+ * @version 3.2.2
70
  */
71
  function enqueue_exchange_rates_script() {
72
+ if (
73
  isset( $_GET['section'] ) &&
74
  in_array( $_GET['section'], array(
75
  'multicurrency',
82
  ) {
83
  wp_enqueue_script( 'wcj-exchange-rates-ajax' );
84
  }
85
+ if (
86
+ isset( $_GET['report'] ) &&
87
+ in_array( $_GET['report'], array(
88
+ 'booster_monthly_sales',
89
+ ) )
90
+ ) {
91
+ wp_enqueue_script( 'wcj-exchange-rates-ajax-average', trailingslashit( wcj_plugin_url() ) . 'includes/js/wcj-ajax-exchange-rates-average.js', array( 'jquery' ), WCJ()->version, true );
92
+ wp_localize_script( 'wcj-exchange-rates-ajax-average', 'ajax_object', array(
93
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
94
+ ) );
95
+ }
96
  }
97
 
98
  /**
includes/functions/wcj-functions-eu-vat.php CHANGED
@@ -2,8 +2,8 @@
2
  /**
3
  * Booster for WooCommerce - Functions - EU VAT
4
  *
5
- * @version 2.9.0
6
- * @version 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
@@ -96,11 +96,18 @@ if ( ! function_exists( 'wcj_validate_vat' ) ) {
96
  /**
97
  * wcj_validate_vat.
98
  *
99
- * @version 2.9.0
100
  * @since 2.9.0
101
  * @return mixed: bool on successful checking (can be true or false), null otherwise
102
  */
103
  function wcj_validate_vat( $country_code, $vat_number ) {
 
 
 
 
 
 
 
104
  $methods = array();
105
  switch ( get_option( 'wcj_eu_vat_number_first_method', 'soap' ) ) {
106
  case 'curl':
2
  /**
3
  * Booster for WooCommerce - Functions - EU VAT
4
  *
5
+ * @version 3.2.2
6
+ * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
96
  /**
97
  * wcj_validate_vat.
98
  *
99
+ * @version 3.2.2
100
  * @since 2.9.0
101
  * @return mixed: bool on successful checking (can be true or false), null otherwise
102
  */
103
  function wcj_validate_vat( $country_code, $vat_number ) {
104
+ if ( '' != ( $skip_countries = get_option( 'wcj_eu_vat_number_advanced_skip_countries', array() ) ) ) {
105
+ $skip_countries = array_map( 'trim', explode( ',', $skip_countries ) );
106
+ $skip_countries = array_map( 'strtoupper', $skip_countries );
107
+ if ( in_array( strtoupper( $country_code ), $skip_countries ) ) {
108
+ return true;
109
+ }
110
+ }
111
  $methods = array();
112
  switch ( get_option( 'wcj_eu_vat_number_first_method', 'soap' ) ) {
113
  case 'curl':
includes/functions/wcj-functions-exchange-rates.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Exchange Rates
4
  *
5
- * @version 2.9.1
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -13,7 +13,7 @@ if ( ! function_exists( 'wcj_get_currency_exchange_rate_servers' ) ) {
13
  /**
14
  * wcj_get_currency_exchange_rate_servers.
15
  *
16
- * @version 2.6.0
17
  * @since 2.6.0
18
  */
19
  function wcj_get_currency_exchange_rate_servers() {
@@ -21,6 +21,7 @@ if ( ! function_exists( 'wcj_get_currency_exchange_rate_servers' ) ) {
21
  'yahoo' => __( 'Yahoo', 'woocommerce-jetpack' ),
22
  'ecb' => __( 'European Central Bank (ECB)', 'woocommerce-jetpack' ),
23
  'tcmb' => __( 'TCMB', 'woocommerce-jetpack' ),
 
24
  );
25
  }
26
  }
@@ -29,7 +30,7 @@ if ( ! function_exists( 'alg_get_exchange_rate' ) ) {
29
  /*
30
  * alg_get_exchange_rate.
31
  *
32
- * @version 2.7.0
33
  * @since 2.6.0
34
  */
35
  function alg_get_exchange_rate( $currency_from, $currency_to ) {
@@ -46,6 +47,9 @@ if ( ! function_exists( 'alg_get_exchange_rate' ) ) {
46
  case 'ecb':
47
  $return = alg_ecb_get_exchange_rate( $currency_from, $currency_to );
48
  break;
 
 
 
49
  default: // 'yahoo'
50
  $return = alg_yahoo_get_exchange_rate( $currency_from, $currency_to );
51
  break;
@@ -167,19 +171,12 @@ if ( ! function_exists( 'alg_yahoo_get_exchange_rate' ) ) {
167
  /*
168
  * alg_yahoo_get_exchange_rate.
169
  *
170
- * @version 2.7.0
171
  * @return float rate on success, else 0
172
  * @todo `alg_` to `wcj_`
173
  */
174
  function alg_yahoo_get_exchange_rate( $currency_from, $currency_to ) {
175
-
176
- $url = "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D" . $currency_from . $currency_to . "%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json";
177
- // $url = 'http://rate-exchange.appspot.com/currency?from=' . $currency_from . '&to=' . $currency_to;
178
-
179
- ob_start();
180
- $max_execution_time = ini_get( 'max_execution_time' );
181
- set_time_limit( 5 );
182
-
183
  $response = '';
184
  if ( 'no' === get_option( 'wcj_currency_exchange_rates_always_curl', 'no' ) && ini_get( 'allow_url_fopen' ) ) {
185
  $response = file_get_contents( $url );
@@ -189,81 +186,95 @@ if ( ! function_exists( 'alg_yahoo_get_exchange_rate' ) ) {
189
  $response = curl_exec( $curl );
190
  curl_close( $curl );
191
  }
192
- $exchange_rate = json_decode( $response );
193
-
194
- set_time_limit( $max_execution_time );
195
- ob_end_clean();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
- return ( isset( $exchange_rate->query->results->row->rate ) ) ? floatval( $exchange_rate->query->results->row->rate ) : 0;
198
- // return ( isset( $exchange_rate->rate ) ) ? $exchange_rate->rate : 0;
 
 
 
 
 
 
 
 
199
  }
200
  }
201
 
202
- if ( ! function_exists( 'wcj_yahoo_get_exchange_rate_average_USD' ) ) {
203
  /*
204
- * wcj_yahoo_get_exchange_rate_average_USD.
205
  *
206
- * @version 2.9.1
207
- * @since 2.5.3
208
  * @return false or rate
209
- * @see https://stackoverflow.com/questions/44075788/yahoo-yql-yahoo-finance-historicaldata-returning-empty-results
210
- * @see https://forums.yahoo.net/t5/Yahoo-Finance-help/Is-Yahoo-Finance-API-broken/td-p/250503/page/3
211
- * @deprecated This feature was discontinued by the Yahoo Finance team and they will not be reintroducing that functionality.
212
  */
213
- function wcj_yahoo_get_exchange_rate_average_USD( $currency, $start_date, $end_date ) {
214
- $url = 'https://query.yahooapis.com/v1/public/yql?q=select%20Close%20from%20yahoo.finance.historicaldata%20where%20symbol%20%3D%20%22'
215
- . $currency . '%3DX%22%20and%20startDate%20%3D%20%22'
216
- . $start_date . '%22%20and%20endDate%20%3D%20%22'
217
- . $end_date. '%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=';
218
- ob_start();
219
- $max_execution_time = ini_get( 'max_execution_time' );
220
- set_time_limit( 15 );
221
- $exchange_rate = json_decode( file_get_contents( $url ) );
222
- set_time_limit( $max_execution_time );
223
- ob_end_clean();
224
- if ( ! isset( $exchange_rate->query->results->quote ) || count( $exchange_rate->query->results->quote ) < 1 ) {
225
- return false;
226
- }
227
- $average_currency = 0;
228
- foreach ( $exchange_rate->query->results->quote as $quote ) {
229
- $average_currency += $quote->Close;
230
- }
231
- $average_currency = $average_currency / count( $exchange_rate->query->results->quote );
232
- if ( 0 == $average_currency ) {
233
- return false;
234
  }
235
- return $average_currency;
 
236
  }
237
  }
238
 
239
- if ( ! function_exists( 'wcj_yahoo_get_exchange_rate_average' ) ) {
240
  /*
241
- * wcj_yahoo_get_exchange_rate_average.
242
  *
243
- * @version 2.9.1
244
- * @since 2.4.7
245
  * @return false or rate
 
246
  */
247
- function wcj_yahoo_get_exchange_rate_average( $currency_from, $currency_to, $start_date, $end_date ) {
248
- // USD / $currency_from
249
- if ( 'USD' != $currency_from ) {
250
- $average_currency_from = wcj_yahoo_get_exchange_rate_average_USD( $currency_from, $start_date, $end_date );
251
- if ( 0 == $average_currency_from ) {
252
- return false;
253
- }
254
- } else {
255
- $average_currency_from = 1.0;
256
- }
257
- // USD / $currency_to
258
- if ( 'USD' != $currency_to ) {
259
- $average_currency_to = wcj_yahoo_get_exchange_rate_average_USD( $currency_to, $start_date, $end_date );
260
- if ( 0 == $average_currency_to ) {
261
- return false;
262
  }
263
- } else {
264
- $average_currency_to = 1.0;
265
  }
266
- // Final rate
267
- return $average_currency_to / $average_currency_from;
268
  }
269
  }
2
  /**
3
  * Booster for WooCommerce - Functions - Exchange Rates
4
  *
5
+ * @version 3.2.2
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
13
  /**
14
  * wcj_get_currency_exchange_rate_servers.
15
  *
16
+ * @version 3.2.2
17
  * @since 2.6.0
18
  */
19
  function wcj_get_currency_exchange_rate_servers() {
21
  'yahoo' => __( 'Yahoo', 'woocommerce-jetpack' ),
22
  'ecb' => __( 'European Central Bank (ECB)', 'woocommerce-jetpack' ),
23
  'tcmb' => __( 'TCMB', 'woocommerce-jetpack' ),
24
+ 'fixer' => __( 'Fixer.io', 'woocommerce-jetpack' ),
25
  );
26
  }
27
  }
30
  /*
31
  * alg_get_exchange_rate.
32
  *
33
+ * @version 3.2.2
34
  * @since 2.6.0
35
  */
36
  function alg_get_exchange_rate( $currency_from, $currency_to ) {
47
  case 'ecb':
48
  $return = alg_ecb_get_exchange_rate( $currency_from, $currency_to );
49
  break;
50
+ case 'fixer':
51
+ $return = alg_fixer_io_get_exchange_rate( $currency_from, $currency_to );
52
+ break;
53
  default: // 'yahoo'
54
  $return = alg_yahoo_get_exchange_rate( $currency_from, $currency_to );
55
  break;
171
  /*
172
  * alg_yahoo_get_exchange_rate.
173
  *
174
+ * @version 3.2.2
175
  * @return float rate on success, else 0
176
  * @todo `alg_` to `wcj_`
177
  */
178
  function alg_yahoo_get_exchange_rate( $currency_from, $currency_to ) {
179
+ $url = "https://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json";
 
 
 
 
 
 
 
180
  $response = '';
181
  if ( 'no' === get_option( 'wcj_currency_exchange_rates_always_curl', 'no' ) && ini_get( 'allow_url_fopen' ) ) {
182
  $response = file_get_contents( $url );
186
  $response = curl_exec( $curl );
187
  curl_close( $curl );
188
  }
189
+ $response = json_decode( $response );
190
+ if ( ! isset( $response->list->resources ) ) {
191
+ return false;
192
+ }
193
+ $currencies = array(
194
+ 'currency_from' => array(
195
+ 'name' => $currency_from . '=X',
196
+ 'usd_rate' => false,
197
+ ),
198
+ 'currency_to' => array(
199
+ 'name' => $currency_to . '=X',
200
+ 'usd_rate' => false,
201
+ ),
202
+ );
203
+ foreach ( $currencies as &$currency ) {
204
+ foreach ( $response->list->resources as $resource ) {
205
+ if ( isset( $resource->resource->fields->symbol ) && $currency['name'] === $resource->resource->fields->symbol ) {
206
+ if ( ! isset( $resource->resource->fields->price ) ) {
207
+ return false;
208
+ }
209
+ $currency['usd_rate'] = $resource->resource->fields->price;
210
+ break;
211
+ }
212
+ }
213
+ }
214
+ return ( false == $currencies['currency_to']['usd_rate'] || false == $currencies['currency_from']['usd_rate'] ? false :
215
+ round( ( $currencies['currency_to']['usd_rate'] / $currencies['currency_from']['usd_rate'] ), 6 ) );
216
+ }
217
+ }
218
 
219
+ if ( ! function_exists( 'alg_fixer_io_get_exchange_rate' ) ) {
220
+ /*
221
+ * alg_fixer_io_get_exchange_rate.
222
+ *
223
+ * @version 3.2.2
224
+ * @since 3.2.2
225
+ * @return false or rate
226
+ */
227
+ function alg_fixer_io_get_exchange_rate( $currency_from, $currency_to ) {
228
+ return wcj_fixer_io_get_exchange_rate_by_date( $currency_from, $currency_to, 'latest' );
229
  }
230
  }
231
 
232
+ if ( ! function_exists( 'wcj_fixer_io_get_exchange_rate_by_date' ) ) {
233
  /*
234
+ * wcj_fixer_io_get_exchange_rate_by_date.
235
  *
236
+ * @version 3.2.2
237
+ * @since 3.2.2
238
  * @return false or rate
 
 
 
239
  */
240
+ function wcj_fixer_io_get_exchange_rate_by_date( $currency_from, $currency_to, $date ) {
241
+ $url = 'https://api.fixer.io/' . $date . '?base=' . $currency_from . '&symbols=' . $currency_to;
242
+ $response = '';
243
+ if ( 'no' === get_option( 'wcj_currency_exchange_rates_always_curl', 'no' ) && ini_get( 'allow_url_fopen' ) ) {
244
+ $response = file_get_contents( $url );
245
+ } elseif ( function_exists( 'curl_version' ) ) {
246
+ $curl = curl_init( $url );
247
+ curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 );
248
+ $response = curl_exec( $curl );
249
+ curl_close( $curl );
 
 
 
 
 
 
 
 
 
 
 
250
  }
251
+ $response = json_decode( $response );
252
+ return ( isset( $response->rates->{$currency_to} ) ? $response->rates->{$currency_to} : false );
253
  }
254
  }
255
 
256
+ if ( ! function_exists( 'wcj_fixer_io_get_exchange_rate_average' ) ) {
257
  /*
258
+ * wcj_fixer_io_get_exchange_rate_average.
259
  *
260
+ * @version 3.2.2
261
+ * @since 3.2.2
262
  * @return false or rate
263
+ * @todo customizable '+1 day' (could be '+1 week' etc.)
264
  */
265
+ function wcj_fixer_io_get_exchange_rate_average( $currency_from, $currency_to, $start_date, $end_date ) {
266
+ $average_rate = 0;
267
+ $average_rate_counter = 0;
268
+ $start_date = new DateTime( $start_date );
269
+ $end_date = new DateTime( $end_date );
270
+ for ( $i = $start_date; $i <= $end_date; $i->modify( '+1 day' ) ) {
271
+ $date = $i->format( "Y-m-d" );
272
+ $rate = wcj_fixer_io_get_exchange_rate_by_date( $currency_from, $currency_to, $date );
273
+ if ( false != $rate ) {
274
+ $average_rate += $rate;
275
+ $average_rate_counter++;
 
 
 
 
276
  }
 
 
277
  }
278
+ return ( 0 == $average_rate || 0 == $average_rate_counter ? false : round( ( $average_rate / $average_rate_counter ), 6 ) );
 
279
  }
280
  }
includes/functions/wcj-functions-orders.php CHANGED
@@ -2,13 +2,25 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Orders
4
  *
5
- * @version 3.1.1
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  if ( ! function_exists( 'wcj_get_order_billing_email' ) ) {
13
  /**
14
  * wcj_get_order_billing_email.
@@ -133,42 +145,18 @@ if ( ! function_exists( 'wcj_get_order_item_meta_info' ) ) {
133
  if ( ! function_exists( 'wcj_get_order_statuses' ) ) {
134
  /**
135
  * wcj_get_order_statuses.
136
- */
137
- function wcj_get_order_statuses( $cut_the_prefix ) {
138
- $order_statuses = array(
139
- 'wc-pending' => _x( 'Pending Payment', 'Order status', 'woocommerce' ),
140
- 'wc-processing' => _x( 'Processing', 'Order status', 'woocommerce' ),
141
- 'wc-on-hold' => _x( 'On Hold', 'Order status', 'woocommerce' ),
142
- 'wc-completed' => _x( 'Completed', 'Order status', 'woocommerce' ),
143
- 'wc-cancelled' => _x( 'Cancelled', 'Order status', 'woocommerce' ),
144
- 'wc-refunded' => _x( 'Refunded', 'Order status', 'woocommerce' ),
145
- 'wc-failed' => _x( 'Failed', 'Order status', 'woocommerce' ),
146
- );
147
- $order_statuses = apply_filters( 'wc_order_statuses', $order_statuses );
148
- if ( $cut_the_prefix ) {
149
- $order_statuses_no_prefix = array();
150
- foreach ( $order_statuses as $status => $desc ) {
151
- $order_statuses_no_prefix[ substr( $status, 3 ) ] = $desc;
152
- }
153
- return $order_statuses_no_prefix;
154
- }
155
- return $order_statuses;
156
- }
157
- }
158
-
159
- if ( ! function_exists( 'wcj_get_order_statuses_v2' ) ) {
160
- /**
161
- * wcj_get_order_statuses_v2.
162
  *
163
- * @version 2.9.0
164
  * @since 2.9.0
165
- * @todo check `wcj_get_order_statuses`
166
  */
167
- function wcj_get_order_statuses_v2() {
168
- $result = array();
169
  $statuses = function_exists( 'wc_get_order_statuses' ) ? wc_get_order_statuses() : array();
 
 
 
 
170
  foreach( $statuses as $status => $status_name ) {
171
- $result[ substr( $status, 3 ) ] = $statuses[ $status ];
172
  }
173
  return $result;
174
  }
2
  /**
3
  * Booster for WooCommerce - Functions - Orders
4
  *
5
+ * @version 3.2.2
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
12
+ if ( ! function_exists( 'wcj_get_order_status' ) ) {
13
+ /**
14
+ * wcj_get_order_status.
15
+ *
16
+ * @version 3.2.2
17
+ * @since 3.2.2
18
+ */
19
+ function wcj_get_order_status( $_order ) {
20
+ return ( WCJ_IS_WC_VERSION_BELOW_3 ? $_order->post_status : $_order->get_status() );
21
+ }
22
+ }
23
+
24
  if ( ! function_exists( 'wcj_get_order_billing_email' ) ) {
25
  /**
26
  * wcj_get_order_billing_email.
145
  if ( ! function_exists( 'wcj_get_order_statuses' ) ) {
146
  /**
147
  * wcj_get_order_statuses.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  *
149
+ * @version 3.2.2
150
  * @since 2.9.0
 
151
  */
152
+ function wcj_get_order_statuses( $cut_prefix = true ) {
 
153
  $statuses = function_exists( 'wc_get_order_statuses' ) ? wc_get_order_statuses() : array();
154
+ if ( ! $cut_prefix ) {
155
+ return $statuses;
156
+ }
157
+ $result = array();
158
  foreach( $statuses as $status => $status_name ) {
159
+ $result[ substr( $status, 3 ) ] = $status_name;
160
  }
161
  return $result;
162
  }
includes/functions/wcj-functions-price-currency.php CHANGED
@@ -2,19 +2,37 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Price and Currency
4
  *
5
- * @version 3.2.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  if ( ! function_exists( 'wcj_add_change_price_hooks' ) ) {
13
  /**
14
  * wcj_add_change_price_hooks.
15
  *
16
  * @version 2.7.0
17
  * @since 2.7.0
 
18
  */
19
  function wcj_add_change_price_hooks( $module_object, $priority, $include_shipping = true ) {
20
  // Prices
@@ -431,10 +449,34 @@ if ( ! function_exists( 'wcj_get_currency_exchange_rate' ) ) {
431
  if ( ! function_exists( 'wc_get_product_purchase_price' ) ) {
432
  /**
433
  * wc_get_product_purchase_price.
 
 
434
  */
435
  function wc_get_product_purchase_price( $product_id = 0 ) {
436
- $the_product = wcj_get_product( $product_id );
437
- return $the_product->get_purchase_price();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438
  }
439
  }
440
 
2
  /**
3
  * Booster for WooCommerce - Functions - Price and Currency
4
  *
5
+ * @version 3.2.2
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
12
+ if ( ! function_exists( 'wcj_get_module_price_hooks_priority' ) ) {
13
+ /**
14
+ * wcj_get_module_price_hooks_priority.
15
+ *
16
+ * @version 3.2.2
17
+ * @since 3.2.2
18
+ * @todo add all corresponding modules
19
+ */
20
+ function wcj_get_module_price_hooks_priority( $module_id ) {
21
+ $modules_priorities = array(
22
+ 'multicurrency' => PHP_INT_MAX - 1,
23
+ 'price_by_user_role' => PHP_INT_MAX - 200,
24
+ );
25
+ return ( 0 != ( $priority = get_option( 'wcj_' . $module_id . '_advanced_price_hooks_priority', 0 ) ) ? $priority : $modules_priorities[ $module_id ] );
26
+ }
27
+ }
28
+
29
  if ( ! function_exists( 'wcj_add_change_price_hooks' ) ) {
30
  /**
31
  * wcj_add_change_price_hooks.
32
  *
33
  * @version 2.7.0
34
  * @since 2.7.0
35
+ * @todo use `$module_object->price_hooks_priority` instead of passing `$priority` argument
36
  */
37
  function wcj_add_change_price_hooks( $module_object, $priority, $include_shipping = true ) {
38
  // Prices
449
  if ( ! function_exists( 'wc_get_product_purchase_price' ) ) {
450
  /**
451
  * wc_get_product_purchase_price.
452
+ *
453
+ * @version 3.2.2
454
  */
455
  function wc_get_product_purchase_price( $product_id = 0 ) {
456
+ if ( 0 == $product_id ) {
457
+ $product_id = get_the_ID();
458
+ }
459
+ $purchase_price = 0;
460
+ if ( 'yes' === get_option( 'wcj_purchase_price_enabled', 'yes' ) ) {
461
+ $purchase_price += (int) get_post_meta( $product_id, '_' . 'wcj_purchase_price' , true );
462
+ }
463
+ if ( 'yes' === get_option( 'wcj_purchase_price_extra_enabled', 'yes' ) ) {
464
+ $purchase_price += (int) get_post_meta( $product_id, '_' . 'wcj_purchase_price_extra', true );
465
+ }
466
+ if ( 'yes' === get_option( 'wcj_purchase_price_affiliate_commission_enabled', 'no' ) ) {
467
+ $purchase_price += (int) get_post_meta( $product_id, '_' . 'wcj_purchase_price_affiliate_commission', true );
468
+ }
469
+ $total_number = apply_filters( 'booster_get_option', 1, get_option( 'wcj_purchase_data_custom_price_fields_total_number', 1 ) );
470
+ for ( $i = 1; $i <= $total_number; $i++ ) {
471
+ if ( '' == get_option( 'wcj_purchase_data_custom_price_field_name_' . $i, '' ) ) {
472
+ continue;
473
+ }
474
+ $meta_value = (int) get_post_meta( $product_id, '_' . 'wcj_purchase_price_custom_field_' . $i, true );
475
+ if ( 0 != $meta_value ) {
476
+ $purchase_price += ( 'fixed' === get_option( 'wcj_purchase_data_custom_price_field_type_' . $i, 'fixed' ) ) ? $meta_value : $purchase_price * $meta_value / 100.0;
477
+ }
478
+ }
479
+ return apply_filters( 'wcj_get_product_purchase_price', $purchase_price, $product_id );
480
  }
481
  }
482
 
includes/functions/wcj-functions-products.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Products
4
  *
5
- * @version 3.2.1
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -57,19 +57,6 @@ if ( ! function_exists( 'wcj_is_enabled_for_product' ) ) {
57
  }
58
  }
59
 
60
- if ( ! function_exists( 'wcj_get_product' ) ) {
61
- /*
62
- * wcj_get_product.
63
- */
64
- function wcj_get_product( $product_id = 0 ) {
65
- if ( 0 == $product_id ) {
66
- $product_id = get_the_ID();
67
- }
68
- $the_product = new WCJ_Product( $product_id );
69
- return $the_product;
70
- }
71
- }
72
-
73
  if ( ! function_exists( 'wcj_get_product_id' ) ) {
74
  /**
75
  * wcj_get_product_id.
2
  /**
3
  * Booster for WooCommerce - Functions - Products
4
  *
5
+ * @version 3.2.2
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
57
  }
58
  }
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  if ( ! function_exists( 'wcj_get_product_id' ) ) {
61
  /**
62
  * wcj_get_product_id.
includes/functions/wcj-functions-users.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Users
4
  *
5
- * @version 3.2.1
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -86,7 +86,7 @@ if ( ! function_exists( 'wcj_get_current_user_first_role' ) ) {
86
  /**
87
  * wcj_get_current_user_first_role.
88
  *
89
- * @version 2.9.0
90
  * @since 2.5.3
91
  */
92
  function wcj_get_current_user_first_role() {
@@ -97,7 +97,8 @@ if ( ! function_exists( 'wcj_get_current_user_first_role' ) ) {
97
  }
98
  }
99
  $current_user = wp_get_current_user();
100
- return ( isset( $current_user->roles[0] ) && '' != $current_user->roles[0] ) ? $current_user->roles[0] : 'guest';
 
101
  }
102
  }
103
 
2
  /**
3
  * Booster for WooCommerce - Functions - Users
4
  *
5
+ * @version 3.2.2
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
86
  /**
87
  * wcj_get_current_user_first_role.
88
  *
89
+ * @version 3.2.2
90
  * @since 2.5.3
91
  */
92
  function wcj_get_current_user_first_role() {
97
  }
98
  }
99
  $current_user = wp_get_current_user();
100
+ $first_role = ( isset( $current_user->roles ) && is_array( $current_user->roles ) && ! empty( $current_user->roles ) ? reset( $current_user->roles ) : 'guest' );
101
+ return ( '' != $first_role ? $first_role : 'guest' );
102
  }
103
  }
104
 
includes/js/wcj-ajax-exchange-rates-average.js ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * wcj-ajax-exchange-rates-average.js
3
+ *
4
+ * @version 3.2.2
5
+ * @since 3.2.2
6
+ */
7
+ jQuery(document).ready(function() {
8
+ jQuery(".wcj_grab_average_currency_exchange_rate").click(function(){
9
+ var input_id = '#'+this.getAttribute('input_id');
10
+ var data = {
11
+ 'action': 'wcj_ajax_get_exchange_rates_average',
12
+ 'wcj_currency_from': this.getAttribute('currency_from'),
13
+ 'wcj_currency_to': this.getAttribute('currency_to'),
14
+ 'wcj_start_date': this.getAttribute('start_date'),
15
+ 'wcj_end_date': this.getAttribute('end_date'),
16
+ };
17
+ jQuery(input_id).prop('readonly', true);
18
+ jQuery.ajax({
19
+ type: "POST",
20
+ url: ajax_object.ajax_url,
21
+ data: data,
22
+ success: function(response) {
23
+ if ( 0 != response ) {
24
+ jQuery(input_id).val(parseFloat(response));
25
+ }
26
+ },
27
+ complete: function() {
28
+ jQuery(input_id).prop('readonly', false);
29
+ },
30
+ });
31
+ return false;
32
+ });
33
+ });
includes/js/wcj-order-quantities.js ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * wcj-order-quantities.js
3
+ *
4
+ * @version 3.2.2
5
+ * @version 3.2.2
6
+ */
7
+
8
+ function check_qty(){
9
+ var variation_id = jQuery('[name=variation_id]').val();
10
+ if (0 == variation_id) {
11
+ return;
12
+ }
13
+ var current_qty = jQuery('[name=quantity]').val();
14
+ if (current_qty < parseInt(product_quantities[variation_id]['min_qty'])){
15
+ jQuery('[name=quantity]').val(product_quantities[variation_id]['min_qty']);
16
+ return;
17
+ }
18
+ if (current_qty > parseInt(product_quantities[variation_id]['max_qty'])){
19
+ jQuery('[name=quantity]').val(product_quantities[variation_id]['max_qty']);
20
+ return;
21
+ }
22
+ }
23
+
24
+ jQuery(document).ready(function(){
25
+ jQuery('[name=variation_id]').on('change',check_qty);
26
+ });
includes/js/wcj-product-addons.js CHANGED
@@ -1,8 +1,9 @@
1
  /**
2
  * wcj-product-addons.
3
  *
4
- * version 3.0.0
5
  * since 2.5.3
 
6
  */
7
 
8
  var _ajax_object = ajax_object;
@@ -35,6 +36,9 @@ function change_price() {
35
  if (jQuery(this).is(':checked')) {
36
  data[jQuery(this).attr('name')] = jQuery(this).val();
37
  }
 
 
 
38
  });
39
  jQuery("select[name^='wcj_product_all_products_addons_'], select[name^='wcj_product_per_product_addons_']").each( function () {
40
  data[jQuery(this).attr('name')] = jQuery(this).find(':selected').val();
1
  /**
2
  * wcj-product-addons.
3
  *
4
+ * version 3.2.2
5
  * since 2.5.3
6
+ * todo `text` type - update price not only on change, but on each pressed key
7
  */
8
 
9
  var _ajax_object = ajax_object;
36
  if (jQuery(this).is(':checked')) {
37
  data[jQuery(this).attr('name')] = jQuery(this).val();
38
  }
39
+ if ('text'==jQuery(this).attr('type') && jQuery(this).val()!='') {
40
+ data[jQuery(this).attr('name')] = jQuery(this).val();
41
+ }
42
  });
43
  jQuery("select[name^='wcj_product_all_products_addons_'], select[name^='wcj_product_per_product_addons_']").each( function () {
44
  data[jQuery(this).attr('name')] = jQuery(this).find(':selected').val();
includes/pdf-invoices/class-wcj-pdf-invoicing-renumerate-tool.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Renumerate Tool
4
  *
5
- * @version 2.3.10
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,19 +15,24 @@ class WCJ_PDF_Invoicing_Renumerate_Tool {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 2.3.10
19
  */
20
  function __construct() {
 
21
  }
22
 
23
  /**
24
  * wcj_multi_selected.
25
  */
26
  function wcj_multi_selected( $selected, $current_multi ) {
27
- if ( ! is_array( $current_multi ) ) return selected( $selected, $current_multi, false );
 
 
28
  foreach( $current_multi as $current ) {
29
  $selected_single = selected( $selected, $current, false );
30
- if ( '' != $selected_single ) return $selected_single;
 
 
31
  }
32
  return '';
33
  }
@@ -35,10 +40,11 @@ class WCJ_PDF_Invoicing_Renumerate_Tool {
35
  /**
36
  * Add Renumerate Invoices tool to WooCommerce menu (the content).
37
  *
38
- * @version 2.3.10
39
  */
40
  function create_renumerate_invoices_tool() {
41
- $result_message = '';
 
42
  $renumerate_result = '';
43
 
44
  $the_invoice_type = ( ! empty( $_POST['invoice_type'] ) ) ? $_POST['invoice_type'] : 'invoice';
@@ -46,7 +52,7 @@ class WCJ_PDF_Invoicing_Renumerate_Tool {
46
  $the_start_date = ( ! empty( $_POST['start_date'] ) ) ? $_POST['start_date'] : '';
47
  $the_end_date = ( ! empty( $_POST['end_date'] ) ) ? $_POST['end_date'] : '';
48
  $the_order_statuses = ( ! empty( $_POST['order_statuses'] ) ) ? $_POST['order_statuses'] : array();
49
- $the_delete_all = ( isset( $_POST['delete_all'] ) ) ? true : false;
50
 
51
  if ( isset( $_POST['renumerate_invoices'] ) ) {
52
  if ( ! empty( $the_order_statuses ) ) {
@@ -55,8 +61,8 @@ class WCJ_PDF_Invoicing_Renumerate_Tool {
55
  } else {
56
  $result_message = '<div class="error"><p><strong>' . __( 'Please select at least one order status.', 'woocommerce-jetpack' ) . '</strong></p></div>';
57
  }
58
- //$result_message .= '<p>' . $renumerate_result . '</p>';
59
  }
 
60
  ?><div>
61
  <h2><?php echo __( 'Booster - Renumerate Invoices', 'woocommerce-jetpack' ); ?></h2>
62
  <p><?php echo __( 'The tool renumerates invoices from choosen date. Invoice number format is set in WooCommerce > Settings > Booster > PDF Invoicing & Packing Slips > Numbering.', 'woocommerce-jetpack' ); ?></p>
@@ -67,56 +73,60 @@ class WCJ_PDF_Invoicing_Renumerate_Tool {
67
  // Start Date
68
  $data[] = array(
69
  __( 'Start Date', 'woocommerce-jetpack' ),
70
- '<input class="input-text" display="date" type="text" name="start_date" value="' . $the_start_date . '">',
71
  '<em>' . __( 'Date to start renumerating. Leave blank to renumerate all invoices.', 'woocommerce-jetpack' ) . '</em>',
72
  );
73
 
74
  // End Date
75
  $data[] = array(
76
  __( 'End Date', 'woocommerce-jetpack' ),
77
- '<input class="input-text" display="date" type="text" name="end_date" value="' . $the_end_date . '">',
78
  '<em>' . __( 'Date to end renumerating. Leave blank to renumerate all invoices.', 'woocommerce-jetpack' ) . '</em>',
79
  );
80
 
81
  // Number
82
  $data[] = array(
83
  __( 'Start Number', 'woocommerce-jetpack' ),
84
- '<input class="input-text" type="text" name="start_number" value="' . $the_start_number . '">',
85
  '<em>' . __( 'Counter to start renumerating. Leave 0 to continue from current counter.', 'woocommerce-jetpack' ) . '</em>',
86
  );
87
 
88
  // Delete All
89
  $data[] = array(
90
  __( 'Delete All', 'woocommerce-jetpack' ),
91
- '<input type="checkbox" name="delete_all" value="" ' . checked( $the_delete_all, true, false ) . '>',
92
- '<em>' . __( 'Clear all invoices before renumerating.', 'woocommerce-jetpack' ) . '</em>',
 
93
  );
94
 
95
  // Type
96
- $invoice_type_select_html = '<select name="invoice_type">';
97
- //$invoice_types = wcj_get_invoice_types();
98
- $invoice_types = wcj_get_enabled_invoice_types();
99
  foreach ( $invoice_types as $invoice_type ) {
100
- $invoice_type_select_html .= '<option value="' . $invoice_type['id'] . '" ' . selected( $invoice_type['id'], $the_invoice_type, false ) . '>' . $invoice_type['title'] . '</option>';
 
101
  }
102
  $invoice_type_select_html .= '</select>';
103
  $data[] = array( __( 'Document Type', 'woocommerce-jetpack' ), $invoice_type_select_html, '', );
104
 
105
  // Statuses
106
- $order_statuses_select_html = '<select id="order_statuses" name="order_statuses[]" multiple size="5">';
107
  $order_statuses = wcj_get_order_statuses( false );
108
  foreach ( $order_statuses as $status => $desc ) {
109
- //$order_statuses_select_html .= '<option value="' . $status . '">' . $desc . '</option>';
110
  $order_statuses_select_html .= '<option value="' . $status . '" ' . $this->wcj_multi_selected( $status, $the_order_statuses ) . '>' . $desc . '</option>';
111
  }
112
  $order_statuses_select_html .= '</select>';
113
  $data[] = array( __( 'Order Statuses', 'woocommerce-jetpack' ), $order_statuses_select_html, '', );
114
 
115
  // Button
116
- $data[] = array( '<input class="button-primary" type="submit" name="renumerate_invoices" value="' . __( 'Renumerate invoices', 'woocommerce-jetpack' ) . '">', '', '' );
 
 
 
 
117
 
118
  // Print all
119
- echo wcj_get_table_html( $data, array( 'table_heading_type' => 'vertical', ) );
120
 
121
  ?>
122
  </form></p>
@@ -171,7 +181,9 @@ class WCJ_PDF_Invoicing_Renumerate_Tool {
171
 
172
  $loop = new WP_Query( $args );
173
 
174
- if ( ! $loop->have_posts() ) break;
 
 
175
 
176
  while ( $loop->have_posts() ) : $loop->the_post();
177
 
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Renumerate Tool
4
  *
5
+ * @version 3.2.2
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.2.2
19
  */
20
  function __construct() {
21
+ return true;
22
  }
23
 
24
  /**
25
  * wcj_multi_selected.
26
  */
27
  function wcj_multi_selected( $selected, $current_multi ) {
28
+ if ( ! is_array( $current_multi ) ) {
29
+ return selected( $selected, $current_multi, false );
30
+ }
31
  foreach( $current_multi as $current ) {
32
  $selected_single = selected( $selected, $current, false );
33
+ if ( '' != $selected_single ) {
34
+ return $selected_single;
35
+ }
36
  }
37
  return '';
38
  }
40
  /**
41
  * Add Renumerate Invoices tool to WooCommerce menu (the content).
42
  *
43
+ * @version 3.2.2
44
  */
45
  function create_renumerate_invoices_tool() {
46
+
47
+ $result_message = '';
48
  $renumerate_result = '';
49
 
50
  $the_invoice_type = ( ! empty( $_POST['invoice_type'] ) ) ? $_POST['invoice_type'] : 'invoice';
52
  $the_start_date = ( ! empty( $_POST['start_date'] ) ) ? $_POST['start_date'] : '';
53
  $the_end_date = ( ! empty( $_POST['end_date'] ) ) ? $_POST['end_date'] : '';
54
  $the_order_statuses = ( ! empty( $_POST['order_statuses'] ) ) ? $_POST['order_statuses'] : array();
55
+ $the_delete_all = ( isset( $_POST['delete_all'] ) );
56
 
57
  if ( isset( $_POST['renumerate_invoices'] ) ) {
58
  if ( ! empty( $the_order_statuses ) ) {
61
  } else {
62
  $result_message = '<div class="error"><p><strong>' . __( 'Please select at least one order status.', 'woocommerce-jetpack' ) . '</strong></p></div>';
63
  }
 
64
  }
65
+
66
  ?><div>
67
  <h2><?php echo __( 'Booster - Renumerate Invoices', 'woocommerce-jetpack' ); ?></h2>
68
  <p><?php echo __( 'The tool renumerates invoices from choosen date. Invoice number format is set in WooCommerce > Settings > Booster > PDF Invoicing & Packing Slips > Numbering.', 'woocommerce-jetpack' ); ?></p>
73
  // Start Date
74
  $data[] = array(
75
  __( 'Start Date', 'woocommerce-jetpack' ),
76
+ '<input class="input-text widefat" display="date" type="text" name="start_date" value="' . $the_start_date . '">',
77
  '<em>' . __( 'Date to start renumerating. Leave blank to renumerate all invoices.', 'woocommerce-jetpack' ) . '</em>',
78
  );
79
 
80
  // End Date
81
  $data[] = array(
82
  __( 'End Date', 'woocommerce-jetpack' ),
83
+ '<input class="input-text widefat" display="date" type="text" name="end_date" value="' . $the_end_date . '">',
84
  '<em>' . __( 'Date to end renumerating. Leave blank to renumerate all invoices.', 'woocommerce-jetpack' ) . '</em>',
85
  );
86
 
87
  // Number
88
  $data[] = array(
89
  __( 'Start Number', 'woocommerce-jetpack' ),
90
+ '<input class="input-text widefat" type="text" name="start_number" value="' . $the_start_number . '">',
91
  '<em>' . __( 'Counter to start renumerating. Leave 0 to continue from current counter.', 'woocommerce-jetpack' ) . '</em>',
92
  );
93
 
94
  // Delete All
95
  $data[] = array(
96
  __( 'Delete All', 'woocommerce-jetpack' ),
97
+ '<input id="wcj_renumerate_invoices_delete_all" type="checkbox" name="delete_all" value="" ' . checked( $the_delete_all, true, false ) . '>' . ' ' .
98
+ '<label for="wcj_renumerate_invoices_delete_all">' . __( 'Clear all invoices before renumerating', 'woocommerce-jetpack' ) . '</label>',
99
+ '',
100
  );
101
 
102
  // Type
103
+ $invoice_type_select_html = '<select class="widefat" name="invoice_type">';
104
+ $invoice_types = wcj_get_enabled_invoice_types();
 
105
  foreach ( $invoice_types as $invoice_type ) {
106
+ $invoice_type_select_html .= '<option value="' . $invoice_type['id'] . '" ' . selected( $invoice_type['id'], $the_invoice_type, false ) . '>' .
107
+ $invoice_type['title'] . '</option>';
108
  }
109
  $invoice_type_select_html .= '</select>';
110
  $data[] = array( __( 'Document Type', 'woocommerce-jetpack' ), $invoice_type_select_html, '', );
111
 
112
  // Statuses
113
+ $order_statuses_select_html = '<select class="widefat" id="order_statuses" name="order_statuses[]" multiple size="5">';
114
  $order_statuses = wcj_get_order_statuses( false );
115
  foreach ( $order_statuses as $status => $desc ) {
 
116
  $order_statuses_select_html .= '<option value="' . $status . '" ' . $this->wcj_multi_selected( $status, $the_order_statuses ) . '>' . $desc . '</option>';
117
  }
118
  $order_statuses_select_html .= '</select>';
119
  $data[] = array( __( 'Order Statuses', 'woocommerce-jetpack' ), $order_statuses_select_html, '', );
120
 
121
  // Button
122
+ $data[] = array(
123
+ '<input class="button-primary" type="submit" name="renumerate_invoices" value="' . __( 'Renumerate invoices', 'woocommerce-jetpack' ) . '">',
124
+ '',
125
+ ''
126
+ );
127
 
128
  // Print all
129
+ echo wcj_get_table_html( $data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical', ) );
130
 
131
  ?>
132
  </form></p>
181
 
182
  $loop = new WP_Query( $args );
183
 
184
+ if ( ! $loop->have_posts() ) {
185
+ break;
186
+ }
187
 
188
  while ( $loop->have_posts() ) : $loop->the_post();
189
 
includes/reports/wcj-class-reports-monthly-sales.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Reports - Monthly Sales (with Currency Conversion)
4
  *
5
- * @version 2.9.1
6
  * @since 2.4.7
7
  * @author Algoritmika Ltd.
8
  */
@@ -71,11 +71,10 @@ class WCJ_Reports_Monthly_Sales {
71
  /*
72
  * get_monthly_sales_report.
73
  *
74
- * @version 2.9.1
75
  * @since 2.4.7
76
  * @todo (maybe) visible rows selection by admin (as option)
77
  * @todo (maybe) take not monthly average, but "Close" of closest day (probably create new "Daily Sales (with Currency Conversion)" report)
78
- * @todo (maybe) option to grab average monthly exchange rates from some data server (unfortunately discontinued by the Yahoo)
79
  */
80
  function get_monthly_sales_report() {
81
 
@@ -230,8 +229,16 @@ class WCJ_Reports_Monthly_Sales {
230
  foreach ( $current_months_averages as $currency_from => $currencies_to ) {
231
  foreach ( $currencies_to as $currency_to => $rate ) {
232
  if ( $currency_from != $currency_to ) {
233
- $currency_rates_html .= $currency_from . $currency_to . ' ' .
234
- '<input style="width:50px;font-size:x-small;" type="number" ' .
 
 
 
 
 
 
 
 
235
  'name="wcj_save_currency_rates_array[' . $currency_from . '][' . $currency_to . '][' . $start_date . '][' . $end_date . ']" ' .
236
  'value="' . $rate . '" step="0.000001">' .
237
  '<br>';
2
  /**
3
  * Booster for WooCommerce - Reports - Monthly Sales (with Currency Conversion)
4
  *
5
+ * @version 3.2.2
6
  * @since 2.4.7
7
  * @author Algoritmika Ltd.
8
  */
71
  /*
72
  * get_monthly_sales_report.
73
  *
74
+ * @version 3.2.2
75
  * @since 2.4.7
76
  * @todo (maybe) visible rows selection by admin (as option)
77
  * @todo (maybe) take not monthly average, but "Close" of closest day (probably create new "Daily Sales (with Currency Conversion)" report)
 
78
  */
79
  function get_monthly_sales_report() {
80
 
229
  foreach ( $current_months_averages as $currency_from => $currencies_to ) {
230
  foreach ( $currencies_to as $currency_to => $rate ) {
231
  if ( $currency_from != $currency_to ) {
232
+ $input_id = sanitize_title( $currency_from . '_' . $currency_to . '_' . $start_date . '_' . $end_date );
233
+ $currency_rates_html .= '<a class="wcj_grab_average_currency_exchange_rate" href="#" title="' . __( 'Grab average rate', 'woocommerce-jetpack' ) .
234
+ '" currency_from="' . $currency_from .
235
+ '" currency_to="' . $currency_to .
236
+ '" start_date="' . $start_date .
237
+ '" end_date="' . $end_date .
238
+ '" input_id="' . $input_id .
239
+ '">' . $currency_from . $currency_to .
240
+ '</a> ' .
241
+ '<input id="' . $input_id . '" style="width:50px;font-size:x-small;" type="number" ' .
242
  'name="wcj_save_currency_rates_array[' . $currency_from . '][' . $currency_to . '][' . $start_date . '][' . $end_date . ']" ' .
243
  'value="' . $rate . '" step="0.000001">' .
244
  '<br>';
includes/settings/meta-box/wcj-settings-meta-box-order-quantities.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Settings Meta Box - Order Min/Max Quantities
4
+ *
5
+ * @version 3.2.2
6
+ * @since 3.2.2
7
+ * @author Algoritmika Ltd.
8
+ * @todo test "Set 0 to use global settings. Set -1 to disable"
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
12
+
13
+ $main_product_id = get_the_ID();
14
+ $_product = wc_get_product( $main_product_id );
15
+ if ( ! $_product ) {
16
+ return array();
17
+ }
18
+ $products = array();
19
+ if ( $_product->is_type( 'variable' ) ) {
20
+ $available_variations = $_product->get_available_variations();
21
+ foreach ( $available_variations as $variation ) {
22
+ $variation_product = wc_get_product( $variation['variation_id'] );
23
+ $products[ $variation['variation_id'] ] = ' (' . wcj_get_product_formatted_variation( $variation_product, true ) . ')';
24
+ }
25
+ } else {
26
+ $products[ $main_product_id ] = '';
27
+ }
28
+ $quantities = array();
29
+ foreach ( $products as $product_id => $desc ) {
30
+ if ( 'yes' === apply_filters( 'booster_get_option', 'no', get_option( 'wcj_order_quantities_min_per_item_quantity_per_product', 'no' ) ) ) {
31
+ $quantities = array_merge( $quantities, array(
32
+ array(
33
+ 'name' => 'wcj_order_quantities_min' . '_' . $product_id,
34
+ 'default' => '',
35
+ 'type' => 'number',
36
+ 'title' => __( 'Minimum Quantity', 'woocommerce-jetpack' ),
37
+ 'desc' => $desc,
38
+ 'product_id' => $product_id,
39
+ 'meta_name' => '_' . 'wcj_order_quantities_min',
40
+ 'custom_attributes' => 'min="-1"',
41
+ 'tooltip' => __( 'Set 0 to use global settings. Set -1 to disable.', 'woocommerce-jetpack' ),
42
+ ),
43
+ ) );
44
+ }
45
+ if ( 'yes' === apply_filters( 'booster_get_option', 'no', get_option( 'wcj_order_quantities_max_per_item_quantity_per_product', 'no' ) ) ) {
46
+ $quantities = array_merge( $quantities, array(
47
+ array(
48
+ 'name' => 'wcj_order_quantities_max' . '_' . $product_id,
49
+ 'default' => '',
50
+ 'type' => 'number',
51
+ 'title' => __( 'Maximum Quantity', 'woocommerce-jetpack' ),
52
+ 'desc' => $desc,
53
+ 'product_id' => $product_id,
54
+ 'meta_name' => '_' . 'wcj_order_quantities_max',
55
+ 'custom_attributes' => 'min="-1"',
56
+ 'tooltip' => __( 'Set 0 to use global settings. Set -1 to disable.', 'woocommerce-jetpack' ),
57
+ ),
58
+ ) );
59
+ }
60
+ }
61
+ return $quantities;
includes/settings/meta-box/wcj-settings-meta-box-product-addons.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings Meta Box - Product Addons
4
  *
5
- * @version 3.0.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -50,6 +50,7 @@ for ( $i = 1; $i <= $total_number; $i++ ) {
50
  'checkbox' => __( 'Checkbox', 'woocommerce-jetpack' ),
51
  'radio' => __( 'Radio Buttons', 'woocommerce-jetpack' ),
52
  'select' => __( 'Select Box', 'woocommerce-jetpack' ),
 
53
  ),
54
  ),
55
  array(
2
  /**
3
  * Booster for WooCommerce - Settings Meta Box - Product Addons
4
  *
5
+ * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
50
  'checkbox' => __( 'Checkbox', 'woocommerce-jetpack' ),
51
  'radio' => __( 'Radio Buttons', 'woocommerce-jetpack' ),
52
  'select' => __( 'Select Box', 'woocommerce-jetpack' ),
53
+ 'text' => __( 'Text', 'woocommerce-jetpack' ),
54
  ),
55
  ),
56
  array(
includes/settings/wcj-settings-checkout-custom-fields.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Checkout Custom Fields
4
  *
5
- * @version 3.2.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -32,12 +32,50 @@ $settings = array(
32
  'type' => 'checkbox',
33
  ),
34
  array(
35
- 'title' => __( 'Add All Fields to "Order Received" Page', 'woocommerce-jetpack' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
37
  'id' => 'wcj_checkout_custom_fields_add_to_order_received',
38
  'default' => 'yes',
39
  'type' => 'checkbox',
40
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  array(
42
  'title' => __( 'Custom Fields Number', 'woocommerce-jetpack' ),
43
  'desc_tip' => __( 'Click Save changes after you change this number.', 'woocommerce-jetpack' ),
2
  /**
3
  * Booster for WooCommerce - Settings - Checkout Custom Fields
4
  *
5
+ * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
32
  'type' => 'checkbox',
33
  ),
34
  array(
35
+ 'title' => __( 'Emails Fields Template', 'woocommerce-jetpack' ),
36
+ 'desc' => __( 'Before the fields', 'woocommerce-jetpack' ),
37
+ 'id' => 'wcj_checkout_custom_fields_emails_template_before',
38
+ 'default' => '',
39
+ 'type' => 'textarea',
40
+ ),
41
+ array(
42
+ 'desc' => __( 'Each field', 'woocommerce-jetpack' ) . '. ' . wcj_message_replaced_values( array( '%label%', '%value%' ) ),
43
+ 'id' => 'wcj_checkout_custom_fields_emails_template_field',
44
+ 'default' => '<p><strong>%label%:</strong> %value%</p>',
45
+ 'type' => 'textarea',
46
+ ),
47
+ array(
48
+ 'desc' => __( 'After the fields', 'woocommerce-jetpack' ),
49
+ 'id' => 'wcj_checkout_custom_fields_emails_template_after',
50
+ 'default' => '',
51
+ 'type' => 'textarea',
52
+ ),
53
+ array(
54
+ 'title' => __( 'Add All Fields to "Order Received" (i.e. "Thank You") and "View Order" Pages', 'woocommerce-jetpack' ),
55
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
56
  'id' => 'wcj_checkout_custom_fields_add_to_order_received',
57
  'default' => 'yes',
58
  'type' => 'checkbox',
59
  ),
60
+ array(
61
+ 'title' => __( '"Order Received" Fields Template', 'woocommerce-jetpack' ),
62
+ 'desc' => __( 'Before the fields', 'woocommerce-jetpack' ),
63
+ 'id' => 'wcj_checkout_custom_fields_order_received_template_before',
64
+ 'default' => '',
65
+ 'type' => 'textarea',
66
+ ),
67
+ array(
68
+ 'desc' => __( 'Each field', 'woocommerce-jetpack' ) . '. ' . wcj_message_replaced_values( array( '%label%', '%value%' ) ),
69
+ 'id' => 'wcj_checkout_custom_fields_order_received_template_field',
70
+ 'default' => '<p><strong>%label%:</strong> %value%</p>',
71
+ 'type' => 'textarea',
72
+ ),
73
+ array(
74
+ 'desc' => __( 'After the fields', 'woocommerce-jetpack' ),
75
+ 'id' => 'wcj_checkout_custom_fields_order_received_template_after',
76
+ 'default' => '',
77
+ 'type' => 'textarea',
78
+ ),
79
  array(
80
  'title' => __( 'Custom Fields Number', 'woocommerce-jetpack' ),
81
  'desc_tip' => __( 'Click Save changes after you change this number.', 'woocommerce-jetpack' ),
includes/settings/wcj-settings-eu-vat-number.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - EU VAT Number
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo set default value for "wcj_eu_vat_number_add_progress_text" to "yes"
@@ -21,21 +21,21 @@ $settings = array(
21
  'id' => 'wcj_eu_vat_number_field_label',
22
  'default' => __( 'EU VAT Number', 'woocommerce-jetpack' ),
23
  'type' => 'text',
24
- 'css' => 'width:300px;',
25
  ),
26
  array(
27
  'title' => __( 'Placeholder', 'woocommerce-jetpack' ),
28
  'id' => 'wcj_eu_vat_number_field_placeholder',
29
  'default' => __( 'EU VAT Number', 'woocommerce-jetpack' ),
30
  'type' => 'text',
31
- 'css' => 'width:300px;',
32
  ),
33
  array(
34
  'title' => __( 'Description', 'woocommerce-jetpack' ),
35
  'id' => 'wcj_eu_vat_number_field_description',
36
  'default' => '',
37
  'type' => 'text',
38
- 'css' => 'width:300px;',
39
  ),
40
  /*
41
  array(
@@ -78,12 +78,11 @@ $settings = array(
78
  'type' => 'checkbox',
79
  ),
80
  array(
81
- 'title' => '',
82
  'desc' => __( 'Message on not valid', 'woocommerce-jetpack' ),
83
  'id' => 'wcj_eu_vat_number_not_valid_message',
84
  'default' => __( '<strong>EU VAT Number</strong> is not valid.', 'woocommerce-jetpack' ),
85
  'type' => 'textarea',
86
- 'css' => 'width:300px;',
87
  ),
88
  array(
89
  'title' => __( 'First Validation Method', 'woocommerce-jetpack' ),
@@ -106,40 +105,41 @@ $settings = array(
106
  ),
107
  array(
108
  'title' => __( 'Preserve VAT in Base Country', 'woocommerce-jetpack' ),
 
 
 
109
  'desc' => __( 'Yes', 'woocommerce-jetpack' ),
110
  'id' => 'wcj_eu_vat_number_preserve_in_base_country',
111
  'default' => 'no',
112
  'type' => 'checkbox',
113
- 'desc_tip' => apply_filters( 'booster_get_message', '', 'desc' ),
114
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
115
  ),
116
  /*
117
  array(
118
- 'title' => '',
119
  'desc' => __( 'Message if customer is in base country and VAT is NOT exempted.', 'woocommerce-jetpack' ),
120
  'id' => 'wcj_eu_vat_number_preserve_in_base_country_message',
121
  'default' => __( 'EU VAT Number is valid, however VAT is not exempted.', 'woocommerce-jetpack' ),
122
  'type' => 'textarea',
123
- 'css' => 'width:300px;',
124
  ),
125
  */
126
  array(
127
  'title' => __( 'Check for IP Location Country', 'woocommerce-jetpack' ),
 
 
128
  'desc' => __( 'Yes', 'woocommerce-jetpack' ),
129
  'id' => 'wcj_eu_vat_number_check_ip_location_country',
130
  'default' => 'no',
131
  'type' => 'checkbox',
132
- 'desc_tip' => apply_filters( 'booster_get_message', '', 'desc' ),
133
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
134
  ),
135
  /*
136
  array(
137
- 'title' => '',
138
  'desc' => __( 'Message if customer\'s check for IP location country has failed.', 'woocommerce-jetpack' ),
139
  'id' => 'wcj_eu_vat_number_check_ip_location_country_message',
140
  'default' => __( 'IP must be from same country as VAT ID.', 'woocommerce-jetpack' ),
141
  'type' => 'textarea',
142
- 'css' => 'width:300px;',
143
  ),
144
  */
145
  array(
@@ -164,21 +164,21 @@ $settings = array(
164
  'id' => 'wcj_eu_vat_number_progress_text_validating',
165
  'default' => __( 'Validating VAT. Please wait...', 'woocommerce-jetpack' ),
166
  'type' => 'text',
167
- 'css' => 'width:300px;',
168
  ),
169
  array(
170
  'title' => __( 'Progress Message: Valid', 'woocommerce-jetpack' ),
171
  'id' => 'wcj_eu_vat_number_progress_text_valid',
172
  'default' => __( 'VAT is valid.', 'woocommerce-jetpack' ),
173
  'type' => 'text',
174
- 'css' => 'width:300px;',
175
  ),
176
  array(
177
  'title' => __( 'Progress Message: Not Valid', 'woocommerce-jetpack' ),
178
  'id' => 'wcj_eu_vat_number_progress_text_not_valid',
179
  'default' => __( 'VAT is not valid.', 'woocommerce-jetpack' ),
180
  'type' => 'text',
181
- 'css' => 'width:300px;',
182
  ),
183
  array(
184
  'title' => __( 'Progress Message: Validation Failed', 'woocommerce-jetpack' ),
@@ -186,10 +186,10 @@ $settings = array(
186
  'id' => 'wcj_eu_vat_number_progress_text_validation_failed',
187
  'default' => __( 'Validation failed. Please try again.', 'woocommerce-jetpack' ),
188
  'type' => 'text',
189
- 'css' => 'width:300px;',
190
  ),
191
  array(
192
- 'title' => __( 'Add EU VAT Number Summary Metabox to Order Edit Page', 'woocommerce-jetpack' ),
193
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
194
  'id' => 'wcj_eu_vat_number_add_order_edit_metabox',
195
  'default' => 'no',
@@ -199,5 +199,22 @@ $settings = array(
199
  'type' => 'sectionend',
200
  'id' => 'wcj_eu_vat_number_options',
201
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  );
203
  return $settings;
2
  /**
3
  * Booster for WooCommerce - Settings - EU VAT Number
4
  *
5
+ * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo set default value for "wcj_eu_vat_number_add_progress_text" to "yes"
21
  'id' => 'wcj_eu_vat_number_field_label',
22
  'default' => __( 'EU VAT Number', 'woocommerce-jetpack' ),
23
  'type' => 'text',
24
+ 'css' => 'width:100%;',
25
  ),
26
  array(
27
  'title' => __( 'Placeholder', 'woocommerce-jetpack' ),
28
  'id' => 'wcj_eu_vat_number_field_placeholder',
29
  'default' => __( 'EU VAT Number', 'woocommerce-jetpack' ),
30
  'type' => 'text',
31
+ 'css' => 'width:100%;',
32
  ),
33
  array(
34
  'title' => __( 'Description', 'woocommerce-jetpack' ),
35
  'id' => 'wcj_eu_vat_number_field_description',
36
  'default' => '',
37
  'type' => 'text',
38
+ 'css' => 'width:100%;',
39
  ),
40
  /*
41
  array(
78
  'type' => 'checkbox',
79
  ),
80
  array(
 
81
  'desc' => __( 'Message on not valid', 'woocommerce-jetpack' ),
82
  'id' => 'wcj_eu_vat_number_not_valid_message',
83
  'default' => __( '<strong>EU VAT Number</strong> is not valid.', 'woocommerce-jetpack' ),
84
  'type' => 'textarea',
85
+ 'css' => 'width:100%;',
86
  ),
87
  array(
88
  'title' => __( 'First Validation Method', 'woocommerce-jetpack' ),
105
  ),
106
  array(
107
  'title' => __( 'Preserve VAT in Base Country', 'woocommerce-jetpack' ),
108
+ 'desc_tip' => sprintf( __( 'This will validate the VAT, but won\'t exempt VAT for base country VAT numbers. Base (i.e. store) country is set in %s.', 'woocommerce-jetpack' ),
109
+ '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=general' ) . '">' . __( 'WooCommerce > Settings > General', 'woocommerce-jetpack' ) . '</a>' ) . '<br>' .
110
+ apply_filters( 'booster_get_message', '', 'desc' ),
111
  'desc' => __( 'Yes', 'woocommerce-jetpack' ),
112
  'id' => 'wcj_eu_vat_number_preserve_in_base_country',
113
  'default' => 'no',
114
  'type' => 'checkbox',
 
115
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
116
  ),
117
  /*
118
  array(
 
119
  'desc' => __( 'Message if customer is in base country and VAT is NOT exempted.', 'woocommerce-jetpack' ),
120
  'id' => 'wcj_eu_vat_number_preserve_in_base_country_message',
121
  'default' => __( 'EU VAT Number is valid, however VAT is not exempted.', 'woocommerce-jetpack' ),
122
  'type' => 'textarea',
123
+ 'css' => 'width:100%;',
124
  ),
125
  */
126
  array(
127
  'title' => __( 'Check for IP Location Country', 'woocommerce-jetpack' ),
128
+ 'desc_tip' => __( 'This will check if customer\'s country (located by customer\'s IP) matches the country in entered VAT number.', 'woocommerce-jetpack' ) . '<br>' .
129
+ apply_filters( 'booster_get_message', '', 'desc' ),
130
  'desc' => __( 'Yes', 'woocommerce-jetpack' ),
131
  'id' => 'wcj_eu_vat_number_check_ip_location_country',
132
  'default' => 'no',
133
  'type' => 'checkbox',
 
134
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
135
  ),
136
  /*
137
  array(
 
138
  'desc' => __( 'Message if customer\'s check for IP location country has failed.', 'woocommerce-jetpack' ),
139
  'id' => 'wcj_eu_vat_number_check_ip_location_country_message',
140
  'default' => __( 'IP must be from same country as VAT ID.', 'woocommerce-jetpack' ),
141
  'type' => 'textarea',
142
+ 'css' => 'width:100%;',
143
  ),
144
  */
145
  array(
164
  'id' => 'wcj_eu_vat_number_progress_text_validating',
165
  'default' => __( 'Validating VAT. Please wait...', 'woocommerce-jetpack' ),
166
  'type' => 'text',
167
+ 'css' => 'width:100%;',
168
  ),
169
  array(
170
  'title' => __( 'Progress Message: Valid', 'woocommerce-jetpack' ),
171
  'id' => 'wcj_eu_vat_number_progress_text_valid',
172
  'default' => __( 'VAT is valid.', 'woocommerce-jetpack' ),
173
  'type' => 'text',
174
+ 'css' => 'width:100%;',
175
  ),
176
  array(
177
  'title' => __( 'Progress Message: Not Valid', 'woocommerce-jetpack' ),
178
  'id' => 'wcj_eu_vat_number_progress_text_not_valid',
179
  'default' => __( 'VAT is not valid.', 'woocommerce-jetpack' ),
180
  'type' => 'text',
181
+ 'css' => 'width:100%;',
182
  ),
183
  array(
184
  'title' => __( 'Progress Message: Validation Failed', 'woocommerce-jetpack' ),
186
  'id' => 'wcj_eu_vat_number_progress_text_validation_failed',
187
  'default' => __( 'Validation failed. Please try again.', 'woocommerce-jetpack' ),
188
  'type' => 'text',
189
+ 'css' => 'width:100%;',
190
  ),
191
  array(
192
+ 'title' => __( 'Add EU VAT Number Summary Meta Box to Admin Order Edit Page', 'woocommerce-jetpack' ),
193
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
194
  'id' => 'wcj_eu_vat_number_add_order_edit_metabox',
195
  'default' => 'no',
199
  'type' => 'sectionend',
200
  'id' => 'wcj_eu_vat_number_options',
201
  ),
202
+ array(
203
+ 'title' => __( 'Advanced Options', 'woocommerce-jetpack' ),
204
+ 'type' => 'title',
205
+ 'id' => 'wcj_eu_vat_number_advanced_options',
206
+ ),
207
+ array(
208
+ 'title' => __( 'Skip VAT Validation for Selected Countries', 'woocommerce-jetpack' ),
209
+ 'desc_tip' => __( 'List all countries you want VAT validation to be skipped for (i.e. VAT always valid). Ignored if empty.', 'woocommerce-jetpack' ),
210
+ 'desc' => sprintf( __( 'Enter country codes as comma separated list, e.g. %s.', 'woocommerce-jetpack' ), '<code>IT,NL</code>' ),
211
+ 'id' => 'wcj_eu_vat_number_advanced_skip_countries',
212
+ 'default' => '',
213
+ 'type' => 'text',
214
+ ),
215
+ array(
216
+ 'type' => 'sectionend',
217
+ 'id' => 'wcj_eu_vat_number_advanced_options',
218
+ ),
219
  );
220
  return $settings;
includes/settings/wcj-settings-multicurrency.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Multicurrency (Currency Switcher)
4
  *
5
- * @version 3.1.3
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo "pretty prices"
@@ -89,6 +89,13 @@ $settings = array(
89
  'type' => 'textarea',
90
  'css' => 'min-width:300px;height:150px;',
91
  ),
 
 
 
 
 
 
 
92
  array(
93
  'type' => 'sectionend',
94
  'id' => 'wcj_multicurrency_options',
2
  /**
3
  * Booster for WooCommerce - Settings - Multicurrency (Currency Switcher)
4
  *
5
+ * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo "pretty prices"
89
  'type' => 'textarea',
90
  'css' => 'min-width:300px;height:150px;',
91
  ),
92
+ array(
93
+ 'title' => __( 'Advanced: Price Filters Priority', 'woocommerce-jetpack' ),
94
+ 'desc_tip' => __( 'Priority for all module\'s price filters. Set to zero to use default priority.' ),
95
+ 'id' => 'wcj_multicurrency_advanced_price_hooks_priority',
96
+ 'default' => 0,
97
+ 'type' => 'number',
98
+ ),
99
  array(
100
  'type' => 'sectionend',
101
  'id' => 'wcj_multicurrency_options',
includes/settings/wcj-settings-my-account.php CHANGED
@@ -22,7 +22,7 @@ return array(
22
  'default' => '',
23
  'type' => 'multiselect',
24
  'class' => 'chosen_select',
25
- 'options' => wcj_get_order_statuses_v2(),
26
  ),
27
  array(
28
  'type' => 'sectionend',
22
  'default' => '',
23
  'type' => 'multiselect',
24
  'class' => 'chosen_select',
25
+ 'options' => wcj_get_order_statuses(),
26
  ),
27
  array(
28
  'type' => 'sectionend',
includes/settings/wcj-settings-order-custom-statuses.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce Settings - Order Custom Statuses
4
  *
5
- * @version 3.1.3
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -20,9 +20,9 @@ return array(
20
  'desc' => __( 'Enable the module to add custom statuses to the list.', 'woocommerce-jetpack' ),
21
  'desc_tip' => __( 'You can change the default order status here. However payment gateways can change this status immediately on order creation. E.g. BACS gateway will change status to On-hold.', 'woocommerce-jetpack' ),
22
  'id' => 'wcj_orders_custom_statuses_default_status',
23
- 'default' => apply_filters( 'woocommerce_default_order_status', 'pending' ),
24
  'type' => 'select',
25
- 'options' => $this->get_order_statuses(),
26
  ),
27
  array(
28
  'title' => __( 'Add All Statuses to Admin Order Bulk Actions', 'woocommerce-jetpack' ),
2
  /**
3
  * Booster for WooCommerce Settings - Order Custom Statuses
4
  *
5
+ * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
20
  'desc' => __( 'Enable the module to add custom statuses to the list.', 'woocommerce-jetpack' ),
21
  'desc_tip' => __( 'You can change the default order status here. However payment gateways can change this status immediately on order creation. E.g. BACS gateway will change status to On-hold.', 'woocommerce-jetpack' ),
22
  'id' => 'wcj_orders_custom_statuses_default_status',
23
+ 'default' => 'wcj_no_changes',
24
  'type' => 'select',
25
+ 'options' => array_merge( array( 'wcj_no_changes' => __( 'No changes', 'woocommerce-jetpack' ) ), wcj_get_order_statuses() ),
26
  ),
27
  array(
28
  'title' => __( 'Add All Statuses to Admin Order Bulk Actions', 'woocommerce-jetpack' ),
includes/settings/wcj-settings-order-quantities.php CHANGED
@@ -2,10 +2,10 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Order Min/Max Quantities
4
  *
5
- * @version 2.9.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
- * @todo maybe generate settings in loop ( min / max )
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
@@ -18,7 +18,7 @@ return array(
18
  ),
19
  array(
20
  'title' => __( 'Minimum Quantity', 'woocommerce-jetpack' ),
21
- 'desc' => __( 'Enable Section', 'woocommerce-jetpack' ),
22
  'id' => 'wcj_order_quantities_min_section_enabled',
23
  'default' => 'no',
24
  'type' => 'checkbox',
@@ -37,7 +37,7 @@ return array(
37
  'id' => 'wcj_order_quantities_min_cart_total_message',
38
  'default' => __( 'Minimum allowed order quantity is %min_cart_total_quantity%. Your current order quantity is %cart_total_quantity%.', 'woocommerce-jetpack' ),
39
  'type' => 'custom_textarea',
40
- 'css' => 'width:66%;min-width:300px;',
41
  ),
42
  array(
43
  'title' => __( 'Per Item Quantity', 'woocommerce-jetpack' ),
@@ -48,13 +48,22 @@ return array(
48
  'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
49
  'custom_attributes' => ( '' === apply_filters( 'booster_get_message', '', 'readonly' ) ? array( 'min' => 0 ) : apply_filters( 'booster_get_message', '', 'readonly' ) ),
50
  ),
 
 
 
 
 
 
 
 
 
51
  array(
52
  'title' => __( 'Message - Per Item Quantity', 'woocommerce-jetpack' ),
53
  'desc' => wcj_message_replaced_values( array( '%product_title%', '%min_per_item_quantity%', '%item_quantity%' ) ),
54
  'id' => 'wcj_order_quantities_min_per_item_message',
55
  'default' => __( 'Minimum allowed quantity for %product_title% is %min_per_item_quantity%. Your current item quantity is %item_quantity%.', 'woocommerce-jetpack' ),
56
  'type' => 'custom_textarea',
57
- 'css' => 'width:66%;min-width:300px;',
58
  ),
59
  array(
60
  'type' => 'sectionend',
@@ -67,7 +76,7 @@ return array(
67
  ),
68
  array(
69
  'title' => __( 'Maximum Quantity', 'woocommerce-jetpack' ),
70
- 'desc' => __( 'Enable Section', 'woocommerce-jetpack' ),
71
  'id' => 'wcj_order_quantities_max_section_enabled',
72
  'default' => 'no',
73
  'type' => 'checkbox',
@@ -86,7 +95,7 @@ return array(
86
  'id' => 'wcj_order_quantities_max_cart_total_message',
87
  'default' => __( 'Maximum allowed order quantity is %max_cart_total_quantity%. Your current order quantity is %cart_total_quantity%.', 'woocommerce-jetpack' ),
88
  'type' => 'custom_textarea',
89
- 'css' => 'width:66%;min-width:300px;',
90
  ),
91
  array(
92
  'title' => __( 'Per Item Quantity', 'woocommerce-jetpack' ),
@@ -97,13 +106,22 @@ return array(
97
  'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
98
  'custom_attributes' => ( '' === apply_filters( 'booster_get_message', '', 'readonly' ) ? array( 'min' => 0 ) : apply_filters( 'booster_get_message', '', 'readonly' ) ),
99
  ),
 
 
 
 
 
 
 
 
 
100
  array(
101
  'title' => __( 'Message - Per Item Quantity', 'woocommerce-jetpack' ),
102
  'desc' => wcj_message_replaced_values( array( '%product_title%', '%max_per_item_quantity%', '%item_quantity%' ) ),
103
  'id' => 'wcj_order_quantities_max_per_item_message',
104
  'default' => __( 'Maximum allowed quantity for %product_title% is %max_per_item_quantity%. Your current item quantity is %item_quantity%.', 'woocommerce-jetpack' ),
105
  'type' => 'custom_textarea',
106
- 'css' => 'width:66%;min-width:300px;',
107
  ),
108
  array(
109
  'type' => 'sectionend',
2
  /**
3
  * Booster for WooCommerce - Settings - Order Min/Max Quantities
4
  *
5
+ * @version 3.2.2
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
+ * @todo (maybe) generate settings in loop ( min / max )
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
18
  ),
19
  array(
20
  'title' => __( 'Minimum Quantity', 'woocommerce-jetpack' ),
21
+ 'desc' => '<strong>' . __( 'Enable section', 'woocommerce-jetpack' ) . '</strong>',
22
  'id' => 'wcj_order_quantities_min_section_enabled',
23
  'default' => 'no',
24
  'type' => 'checkbox',
37
  'id' => 'wcj_order_quantities_min_cart_total_message',
38
  'default' => __( 'Minimum allowed order quantity is %min_cart_total_quantity%. Your current order quantity is %cart_total_quantity%.', 'woocommerce-jetpack' ),
39
  'type' => 'custom_textarea',
40
+ 'css' => 'width:100%;',
41
  ),
42
  array(
43
  'title' => __( 'Per Item Quantity', 'woocommerce-jetpack' ),
48
  'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
49
  'custom_attributes' => ( '' === apply_filters( 'booster_get_message', '', 'readonly' ) ? array( 'min' => 0 ) : apply_filters( 'booster_get_message', '', 'readonly' ) ),
50
  ),
51
+ array(
52
+ 'title' => __( 'Per Item Quantity on Per Product Basis', 'woocommerce-jetpack' ),
53
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
54
+ 'desc_tip' => __( 'This will add meta box to each product\'s edit page.', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
55
+ 'id' => 'wcj_order_quantities_min_per_item_quantity_per_product',
56
+ 'default' => 'no',
57
+ 'type' => 'checkbox',
58
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
59
+ ),
60
  array(
61
  'title' => __( 'Message - Per Item Quantity', 'woocommerce-jetpack' ),
62
  'desc' => wcj_message_replaced_values( array( '%product_title%', '%min_per_item_quantity%', '%item_quantity%' ) ),
63
  'id' => 'wcj_order_quantities_min_per_item_message',
64
  'default' => __( 'Minimum allowed quantity for %product_title% is %min_per_item_quantity%. Your current item quantity is %item_quantity%.', 'woocommerce-jetpack' ),
65
  'type' => 'custom_textarea',
66
+ 'css' => 'width:100%;',
67
  ),
68
  array(
69
  'type' => 'sectionend',
76
  ),
77
  array(
78
  'title' => __( 'Maximum Quantity', 'woocommerce-jetpack' ),
79
+ 'desc' => '<strong>' . __( 'Enable section', 'woocommerce-jetpack' ) . '</strong>',
80
  'id' => 'wcj_order_quantities_max_section_enabled',
81
  'default' => 'no',
82
  'type' => 'checkbox',
95
  'id' => 'wcj_order_quantities_max_cart_total_message',
96
  'default' => __( 'Maximum allowed order quantity is %max_cart_total_quantity%. Your current order quantity is %cart_total_quantity%.', 'woocommerce-jetpack' ),
97
  'type' => 'custom_textarea',
98
+ 'css' => 'width:100%;',
99
  ),
100
  array(
101
  'title' => __( 'Per Item Quantity', 'woocommerce-jetpack' ),
106
  'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
107
  'custom_attributes' => ( '' === apply_filters( 'booster_get_message', '', 'readonly' ) ? array( 'min' => 0 ) : apply_filters( 'booster_get_message', '', 'readonly' ) ),
108
  ),
109
+ array(
110
+ 'title' => __( 'Per Item Quantity on Per Product Basis', 'woocommerce-jetpack' ),
111
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
112
+ 'desc_tip' => __( 'This will add meta box to each product\'s edit page.', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
113
+ 'id' => 'wcj_order_quantities_max_per_item_quantity_per_product',
114
+ 'default' => 'no',
115
+ 'type' => 'checkbox',
116
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
117
+ ),
118
  array(
119
  'title' => __( 'Message - Per Item Quantity', 'woocommerce-jetpack' ),
120
  'desc' => wcj_message_replaced_values( array( '%product_title%', '%max_per_item_quantity%', '%item_quantity%' ) ),
121
  'id' => 'wcj_order_quantities_max_per_item_message',
122
  'default' => __( 'Maximum allowed quantity for %product_title% is %max_per_item_quantity%. Your current item quantity is %item_quantity%.', 'woocommerce-jetpack' ),
123
  'type' => 'custom_textarea',
124
+ 'css' => 'width:100%;',
125
  ),
126
  array(
127
  'type' => 'sectionend',
includes/settings/wcj-settings-pdf-invoicing-numbering.php CHANGED
@@ -2,15 +2,15 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Numbering
4
  *
5
- * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
- $settings = array();
13
- $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_settings', 'no' ) ) ? wcj_get_enabled_invoice_types() : wcj_get_invoice_types();
14
  foreach ( $invoice_types as $invoice_type ) {
15
  $settings = array_merge( $settings, array(
16
  array(
@@ -42,14 +42,19 @@ foreach ( $invoice_types as $invoice_type ) {
42
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_numbering_prefix',
43
  'default' => '',
44
  'type' => 'text',
45
- 'css' => 'width:300px',
46
  ),
47
  array(
48
  'title' => __( 'Suffix', 'woocommerce-jetpack' ),
49
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_numbering_suffix',
50
  'default' => '',
51
  'type' => 'text',
52
- 'css' => 'width:300px',
 
 
 
 
 
 
53
  ),
54
  array(
55
  'type' => 'sectionend',
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Numbering
4
  *
5
+ * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
+ $settings = array();
13
+ $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_settings', 'no' ) ? wcj_get_enabled_invoice_types() : wcj_get_invoice_types() );
14
  foreach ( $invoice_types as $invoice_type ) {
15
  $settings = array_merge( $settings, array(
16
  array(
42
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_numbering_prefix',
43
  'default' => '',
44
  'type' => 'text',
 
45
  ),
46
  array(
47
  'title' => __( 'Suffix', 'woocommerce-jetpack' ),
48
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_numbering_suffix',
49
  'default' => '',
50
  'type' => 'text',
51
+ ),
52
+ array(
53
+ 'title' => __( 'Template', 'woocommerce-jetpack' ),
54
+ 'desc' => '<br>' . wcj_message_replaced_values( array( '%prefix%', '%counter%', '%suffix%' ) ),
55
+ 'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_numbering_template',
56
+ 'default' => '%prefix%%counter%%suffix%',
57
+ 'type' => 'text',
58
  ),
59
  array(
60
  'type' => 'sectionend',
includes/settings/wcj-settings-pdf-invoicing-styling.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Styling
4
  *
5
- * @version 3.2.1
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -57,7 +57,7 @@ foreach ( $invoice_types as $invoice_type ) {
57
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_css',
58
  'default' => $this->get_default_css_template( $invoice_type['id'] ),
59
  'type' => 'textarea',
60
- 'css' => 'width:100%;height:200px;',
61
  ),
62
  ),
63
  array( $font_family_option ),
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Styling
4
  *
5
+ * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
57
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_css',
58
  'default' => $this->get_default_css_template( $invoice_type['id'] ),
59
  'type' => 'textarea',
60
+ 'css' => 'width:100%;height:500px;',
61
  ),
62
  ),
63
  array( $font_family_option ),
includes/settings/wcj-settings-pdf-invoicing.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - General
4
  *
5
- * @version 3.2.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -18,7 +18,7 @@ $settings = array(
18
  );
19
  // Hooks Array
20
  $status_change_hooks = array();
21
- $order_statuses = wcj_get_order_statuses( true );
22
  foreach ( $order_statuses as $status => $desc ) {
23
  $status_change_hooks[ 'woocommerce_order_status_' . $status ] = sprintf( __( 'Create on Order Status %s', 'woocommerce-jetpack' ), $desc );
24
  }
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - General
4
  *
5
+ * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
18
  );
19
  // Hooks Array
20
  $status_change_hooks = array();
21
+ $order_statuses = wcj_get_order_statuses();
22
  foreach ( $order_statuses as $status => $desc ) {
23
  $status_change_hooks[ 'woocommerce_order_status_' . $status ] = sprintf( __( 'Create on Order Status %s', 'woocommerce-jetpack' ), $desc );
24
  }
includes/settings/wcj-settings-price-by-user-role.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Price by User Role
4
  *
5
- * @version 3.2.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -65,6 +65,13 @@ $settings = array(
65
  'default' => 'no',
66
  'type' => 'checkbox',
67
  ),
 
 
 
 
 
 
 
68
  array(
69
  'type' => 'sectionend',
70
  'id' => 'wcj_price_by_user_role_options',
2
  /**
3
  * Booster for WooCommerce - Settings - Price by User Role
4
  *
5
+ * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
65
  'default' => 'no',
66
  'type' => 'checkbox',
67
  ),
68
+ array(
69
+ 'title' => __( 'Advanced: Price Filters Priority', 'woocommerce-jetpack' ),
70
+ 'desc_tip' => __( 'Priority for all module\'s price filters. Set to zero to use default priority.' ),
71
+ 'id' => 'wcj_price_by_user_role_advanced_price_hooks_priority',
72
+ 'default' => 0,
73
+ 'type' => 'number',
74
+ ),
75
  array(
76
  'type' => 'sectionend',
77
  'id' => 'wcj_price_by_user_role_options',
includes/settings/wcj-settings-product-addons.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Product Addons
4
  *
5
- * @version 3.0.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo add "frontend template" options
@@ -79,6 +79,7 @@ for ( $i = 1; $i <= $total_number; $i++ ) {
79
  'checkbox' => __( 'Checkbox', 'woocommerce-jetpack' ),
80
  'radio' => __( 'Radio Buttons', 'woocommerce-jetpack' ),
81
  'select' => __( 'Select Box', 'woocommerce-jetpack' ),
 
82
  ),
83
  ),
84
  array(
2
  /**
3
  * Booster for WooCommerce - Settings - Product Addons
4
  *
5
+ * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo add "frontend template" options
79
  'checkbox' => __( 'Checkbox', 'woocommerce-jetpack' ),
80
  'radio' => __( 'Radio Buttons', 'woocommerce-jetpack' ),
81
  'select' => __( 'Select Box', 'woocommerce-jetpack' ),
82
+ 'text' => __( 'Text', 'woocommerce-jetpack' ),
83
  ),
84
  ),
85
  array(
includes/shortcodes/class-wcj-order-items-shortcodes.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Order Items
4
  *
5
- * @version 3.2.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -25,7 +25,7 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
25
  /**
26
  * add_extra_atts.
27
  *
28
- * @version 3.2.0
29
  */
30
  function add_extra_atts( $atts ) {
31
  $modified_atts = array_merge( array(
@@ -59,6 +59,7 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
59
  'refunded_items_table' => 'no',
60
  'hide_zero_prices' => 'no',
61
  'multicolumns_glue' => '<br>',
 
62
  ), $atts );
63
  return $modified_atts;
64
  }
@@ -245,7 +246,8 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
245
  /**
246
  * wcj_order_items_table.
247
  *
248
- * @version 3.2.0
 
249
  * @todo (maybe) `if ( $columns_total_number !== count( $columns_titles ) || $columns_total_number !== count( $columns_styles ) ) { return __( 'Please recheck that there is the same number of columns in "columns", "columns_titles" and "columns_styles" attributes.', 'woocommerce-jetpack' ); }`
250
  */
251
  function wcj_order_items_table( $atts, $content = '' ) {
@@ -372,6 +374,16 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
372
  return '';
373
  }
374
 
 
 
 
 
 
 
 
 
 
 
375
  $html = '';
376
  $table_html_args = array(
377
  'table_class' => $atts['table_class'],
@@ -404,6 +416,25 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
404
  return $html;
405
  }
406
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
  /**
408
  * get_cell.
409
  *
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Order Items
4
  *
5
+ * @version 3.2.2
6
  * @author Algoritmika Ltd.
7
  */
8
 
25
  /**
26
  * add_extra_atts.
27
  *
28
+ * @version 3.2.2
29
  */
30
  function add_extra_atts( $atts ) {
31
  $modified_atts = array_merge( array(
59
  'refunded_items_table' => 'no',
60
  'hide_zero_prices' => 'no',
61
  'multicolumns_glue' => '<br>',
62
+ 'sort_by_column' => 0,
63
  ), $atts );
64
  return $modified_atts;
65
  }
246
  /**
247
  * wcj_order_items_table.
248
  *
249
+ * @version 3.2.2
250
+ * @todo `sort_by_column` - fix `item_number`
251
  * @todo (maybe) `if ( $columns_total_number !== count( $columns_titles ) || $columns_total_number !== count( $columns_styles ) ) { return __( 'Please recheck that there is the same number of columns in "columns", "columns_titles" and "columns_styles" attributes.', 'woocommerce-jetpack' ); }`
252
  */
253
  function wcj_order_items_table( $atts, $content = '' ) {
374
  return '';
375
  }
376
 
377
+ // Sorting
378
+ if ( $atts['sort_by_column'] > 0 ) {
379
+ $this->sort_by_column = $atts['sort_by_column'];
380
+ usort( $data, array( $this, 'sort_data' ) );
381
+ }
382
+
383
+ // Final filter
384
+ $data = apply_filters( 'wcj_order_items_table_data', $data );
385
+
386
+ // Final HTML
387
  $html = '';
388
  $table_html_args = array(
389
  'table_class' => $atts['table_class'],
416
  return $html;
417
  }
418
 
419
+ /**
420
+ * sort_data.
421
+ *
422
+ * @version 3.2.2
423
+ * @since 3.2.2
424
+ * @todo option to sort as numbers or as text
425
+ * @todo use id (e.g. `product_sku`) instead of number
426
+ */
427
+ function sort_data( $a, $b ) {
428
+ $key = ( $this->sort_by_column - 1 );
429
+ if ( ! isset( $a[ $key ] ) || ! isset( $b[ $key ] ) ) {
430
+ return 0;
431
+ }
432
+ if ( $a[ $key ] == $b[ $key ] ) {
433
+ return 0;
434
+ }
435
+ return ( $a[ $key ] < $b[ $key ] ) ? -1 : 1;
436
+ }
437
+
438
  /**
439
  * get_cell.
440
  *
includes/tools/class-wcj-order-statuses-tool.php ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Tool - Order Statuses
4
+ *
5
+ * @version 3.2.2
6
+ * @since 3.2.2
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit;
11
+
12
+ if ( ! class_exists( 'WCJ_Order_Statuses_Tool' ) ) :
13
+
14
+ class WCJ_Order_Statuses_Tool {
15
+
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @version 3.2.2
20
+ * @since 3.2.2
21
+ */
22
+ function __construct( $tool_id, $module ) {
23
+ $this->id = $tool_id;
24
+ $this->module = $module;
25
+ }
26
+
27
+ /**
28
+ * add_custom_status.
29
+ *
30
+ * @version 3.2.2
31
+ */
32
+ function add_custom_status( $new_status, $new_status_label, $new_status_icon_content, $new_status_icon_color ) {
33
+ // Checking function arguments
34
+ if ( '' == $new_status ) {
35
+ return '<div class="error"><p>' . __( 'Status slug is empty. Status was not added!', 'woocommerce-jetpack' ) . '</p></div>';
36
+ }
37
+ if ( strlen( $new_status ) > 17 ) {
38
+ return '<div class="error"><p>' . __( 'The length of status slug must be 17 or less characters (excluding prefix). Status was not added!', 'woocommerce-jetpack' ) .
39
+ '</p></div>';
40
+ }
41
+ if ( '' == $new_status_label ) {
42
+ return '<div class="error"><p>' . __( 'Status label is empty. Status was not added!', 'woocommerce-jetpack' ) . '</p></div>';
43
+ }
44
+ // Checking status for duplicates
45
+ $new_key = 'wc-' . $new_status;
46
+ $all_statuses = wcj_get_order_statuses( false );
47
+ if ( isset( $all_statuses[ $new_key ] ) ) {
48
+ return '<div class="error"><p>' . __( 'Duplicate slug. Status was not added!', 'woocommerce-jetpack' ) . '</p></div>';
49
+ }
50
+ // Adding custom status
51
+ $statuses_updated = $this->module->get_custom_order_statuses();
52
+ $statuses_updated[ $new_key ] = $new_status_label;
53
+ $result = update_option( 'wcj_orders_custom_statuses_array', $statuses_updated );
54
+ $result = update_option( 'wcj_orders_custom_status_icon_data_' . $new_status, array(
55
+ 'content' => $new_status_icon_content,
56
+ 'color' => $new_status_icon_color,
57
+ ) );
58
+ return ( true === $result ?
59
+ '<div class="updated"><p>' . sprintf( __( '%s status has been successfully added.', 'woocommerce-jetpack' ),
60
+ '<code>' . $new_status . '</code>' ) . '</p></div>' :
61
+ '<div class="error"><p>' . sprintf( __( '%s status was not added!', 'woocommerce-jetpack' ),
62
+ '<code>' . $new_status . '</code>' ) . '</p></div>'
63
+ );
64
+ }
65
+
66
+ /**
67
+ * edit_custom_status.
68
+ *
69
+ * @version 3.2.2
70
+ * @since 3.2.2
71
+ */
72
+ function edit_custom_status( $new_status, $new_status_label, $new_status_icon_content, $new_status_icon_color ) {
73
+ if ( '' == $new_status_label ) {
74
+ return '<div class="error"><p>' . __( 'Status label is empty. Status was not edited!', 'woocommerce-jetpack' ) . '</p></div>';
75
+ } else {
76
+ $statuses_updated = $this->module->get_custom_order_statuses();
77
+ $statuses_updated[ 'wc-' . $new_status ] = $new_status_label;
78
+ $result = update_option( 'wcj_orders_custom_statuses_array', $statuses_updated );
79
+ $result_icon_data = update_option( 'wcj_orders_custom_status_icon_data_' . $new_status, array(
80
+ 'content' => $new_status_icon_content,
81
+ 'color' => $new_status_icon_color,
82
+ ) );
83
+ return ( $result || $result_icon_data ?
84
+ '<div class="updated"><p>' . sprintf( __( '%s status has been successfully edited!', 'woocommerce-jetpack' ),
85
+ '<code>' . $new_status . '</code>' ) . '</p></div>' :
86
+ '<div class="error"><p>' . sprintf( __( '%s status was not edited!', 'woocommerce-jetpack' ),
87
+ '<code>' . $new_status . '</code>' ) . '</p></div>'
88
+ );
89
+ }
90
+ }
91
+
92
+ /**
93
+ * delete_custom_status.
94
+ *
95
+ * @version 3.2.2
96
+ * @since 3.2.2
97
+ * @todo (maybe) change all orders to fallback status
98
+ * @todo (maybe) option to change fallback status from 'on-hold' to any other status
99
+ */
100
+ function delete_custom_status( $status ) {
101
+ $statuses_updated = $this->module->get_custom_order_statuses();
102
+ unset( $statuses_updated[ $status ] );
103
+ $result = update_option( 'wcj_orders_custom_statuses_array', $statuses_updated );
104
+ delete_option( 'wcj_orders_custom_status_icon_data_' . substr( $status, 3 ) );
105
+ return ( true === $result ?
106
+ '<div class="updated"><p>' . sprintf( __( '%s status has been successfully deleted.', 'woocommerce-jetpack' ),
107
+ '<code>' . $status . '</code>' ) . '</p></div>' :
108
+ '<div class="error"><p>' . sprintf( __( '%s status delete failed!', 'woocommerce-jetpack' ),
109
+ '<code>' . $status . '</code>' ) . '</p></div>'
110
+ );
111
+ }
112
+
113
+ /**
114
+ * delete_custom_status_all.
115
+ *
116
+ * @version 3.2.2
117
+ * @since 3.2.2
118
+ */
119
+ function delete_custom_status_all() {
120
+ $custom_statuses = $this->module->get_custom_order_statuses( true );
121
+ delete_option( 'wcj_orders_custom_statuses_array' );
122
+ foreach ( $custom_statuses as $slug => $label ) {
123
+ delete_option( 'wcj_orders_custom_status_icon_data_' . $slug );
124
+ }
125
+ wp_safe_redirect( remove_query_arg( 'delete_all' ) );
126
+ exit;
127
+ }
128
+
129
+ /**
130
+ * get_custom_statuses_table.
131
+ *
132
+ * @version 3.2.2
133
+ * @since 3.2.2
134
+ */
135
+ function get_custom_statuses_table() {
136
+ $table_data = array();
137
+ $table_header = array(
138
+ __( 'Slug', 'woocommerce-jetpack' ),
139
+ __( 'Label', 'woocommerce-jetpack' ),
140
+ __( 'Icon Code', 'woocommerce-jetpack' ),
141
+ __( 'Icon Color', 'woocommerce-jetpack' ),
142
+ __( 'Actions', 'woocommerce-jetpack' ),
143
+ );
144
+ $all_statuses = wcj_get_order_statuses( false );
145
+ $custom_statuses = $this->module->get_custom_order_statuses();
146
+ foreach( $all_statuses as $status => $status_name ) {
147
+ $row = array(
148
+ esc_attr( $status ),
149
+ esc_html( $status_name ),
150
+ );
151
+ if ( ! array_key_exists( $status, $custom_statuses ) ) {
152
+ $row = array_merge( $row, array( '', '', '' ) );
153
+ } else {
154
+ $icon_data = $this->module->get_status_icon_data( substr( $status, 3 ) );
155
+ $color_html = '<input disabled type="color" value="' . $icon_data['color'] . '">';
156
+ $delete_button = '<a class="button-primary" href="' . add_query_arg( 'delete', $status, remove_query_arg( 'edit' ) ) .
157
+ '" onclick="return confirm(\'' . __( 'Are you sure?', 'woocommerce-jetpack' ) . '\')">' . __( 'Delete', 'woocommerce-jetpack' ) . '</a>';
158
+ $edit_button = '<a class="button-primary"' . ( '' != apply_filters( 'booster_get_message', '', 'desc' ) ?
159
+ ' disabled title="' . __( 'Get Booster Plus to enable.', 'woocommerce-jetpack' ) . '"' :
160
+ ' href="' . add_query_arg( 'edit', $status, remove_query_arg( 'delete' ) ) . '"' ) . '>' . __( 'Edit', 'woocommerce-jetpack' ) . '</a>';
161
+ $row = array_merge( $row, array(
162
+ $icon_data['content'],
163
+ $color_html,
164
+ $delete_button . ' ' . $edit_button,
165
+ ) );
166
+ }
167
+ $table_data[] = $row;
168
+ }
169
+ $columns_styles = array();
170
+ for ( $i = 1; $i <= 5; $i++ ) {
171
+ $columns_styles[] = 'width:20%;';
172
+ }
173
+ return ( ! empty( $table_data ) ?
174
+ '<h4>' . __( 'Statuses', 'woocommerce-jetpack' ) . '</h4>' .
175
+ wcj_get_table_html( array_merge( array( $table_header ), $table_data ), array(
176
+ 'table_class' => 'widefat striped',
177
+ 'table_heading_type' => 'horizontal',
178
+ 'columns_styles' => $columns_styles,
179
+ ) ) :
180
+ ''
181
+ );
182
+ }
183
+
184
+ /**
185
+ * get_custom_statuses_add_edit_table.
186
+ *
187
+ * @version 3.2.2
188
+ * @since 3.2.2
189
+ */
190
+ function get_custom_statuses_add_edit_table() {
191
+ $is_editing = ( isset( $_GET['edit'] ) ) ? true : false;
192
+ if ( $is_editing ) {
193
+ $edit_slug = $_GET['edit'];
194
+ $custom_order_statuses = $this->module->get_custom_order_statuses();
195
+ $edit_label = isset( $custom_order_statuses[ $edit_slug ] ) ? $custom_order_statuses[ $edit_slug ] : '';
196
+ $edit_icon_data = $this->module->get_status_icon_data( substr( $edit_slug, 3 ) );
197
+ }
198
+ $slug_html = '<input type="text" name="new_status" style="width:100%;"' . ( $is_editing ? ' value="' . substr( $edit_slug, 3 ) . '" readonly' : '' ) . '>';
199
+ $label_html = '<input type="text" name="new_status_label" style="width:100%;"' . ( $is_editing ? ' value="' . $edit_label . '"' : '' ) . '>';
200
+ $icon_code_input_html = '<input type="text" name="new_status_icon_content" value="' . ( $is_editing ? $edit_icon_data['content'] : 'e011' ) . '">';
201
+ $icon_code_tip = '<em>' . sprintf( __( 'You can check icon codes <a target="_blank" href="%s">here</a>.', 'woocommerce-jetpack' ),
202
+ 'https://rawgit.com/woothemes/woocommerce-icons/master/demo.html' ) . '</em>';
203
+ $icon_color_input_html = '<input type="color" name="new_status_icon_color" value="' . ( $is_editing ? $edit_icon_data['color'] : '#999999' ) . '">';
204
+ $action_button = '<input class="button-primary" type="submit" name="' . ( $is_editing ? 'edit_custom_status' : 'add_custom_status' ) . '"' .
205
+ ' value="' . ( $is_editing ? __( 'Edit custom status', 'woocommerce-jetpack' ) : __( 'Add new custom status', 'woocommerce-jetpack' ) ) . '">';
206
+ $clear_button = ( $is_editing ?
207
+ ' <a class="button-primary" href="' . remove_query_arg( array( 'delete', 'edit' ) ) . '">' . __( 'Clear', 'woocommerce-jetpack' ) . '</a>' : '' );
208
+ $table_data = array(
209
+ array(
210
+ __( 'Slug (without <code>wc-</code> prefix)', 'woocommerce-jetpack' ),
211
+ __( 'Label', 'woocommerce-jetpack' ),
212
+ __( 'Icon Code', 'woocommerce-jetpack' ),
213
+ __( 'Icon Color', 'woocommerce-jetpack' ),
214
+ __( 'Actions', 'woocommerce-jetpack' ),
215
+ ),
216
+ array(
217
+ $slug_html,
218
+ $label_html,
219
+ $icon_code_input_html . '<br>' . $icon_code_tip,
220
+ $icon_color_input_html,
221
+ $action_button . $clear_button,
222
+ ),
223
+ );
224
+ $columns_styles = array();
225
+ for ( $i = 1; $i <= 5; $i++ ) {
226
+ $columns_styles[] = 'width:20%;';
227
+ }
228
+ return '<h4>' . ( $is_editing ? __( 'Edit', 'woocommerce-jetpack' ) : __( 'Add', 'woocommerce-jetpack' ) ) . '</h4>' .
229
+ '<form method="post" action="' . remove_query_arg( 'delete' ) . '">' .
230
+ wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'horizontal', 'columns_styles' => $columns_styles ) ) .
231
+ '</form>';
232
+ }
233
+
234
+ /**
235
+ * process_actions.
236
+ *
237
+ * @version 3.2.2
238
+ * @since 3.2.2
239
+ * @todo (maybe) use `init` hook for processing actions
240
+ */
241
+ function process_actions() {
242
+ if ( isset( $_POST['add_custom_status'] ) ) {
243
+ return $this->add_custom_status( sanitize_key( $_POST['new_status'] ), $_POST['new_status_label'], $_POST['new_status_icon_content'], $_POST['new_status_icon_color'] );
244
+ } elseif ( isset( $_POST['edit_custom_status'] ) ) {
245
+ return $this->edit_custom_status( $_POST['new_status'], $_POST['new_status_label'], $_POST['new_status_icon_content'], $_POST['new_status_icon_color'] );
246
+ } elseif ( isset( $_GET['delete'] ) && '' != $_GET['delete'] ) {
247
+ return $this->delete_custom_status( $_GET['delete'] );
248
+ } elseif ( isset( $_GET['delete_all'] ) && '' != $_GET['delete_all'] ) {
249
+ return $this->delete_custom_status_all();
250
+ }
251
+ }
252
+
253
+ /**
254
+ * get_delete_all_custom_statuses_button.
255
+ *
256
+ * @version 3.2.2
257
+ * @since 3.2.2
258
+ */
259
+ function get_delete_all_custom_statuses_button() {
260
+ return '<p>' . '<a class="button-primary" href="' . add_query_arg( 'delete_all', '1', remove_query_arg( array( 'edit', 'delete' ) ) ) .
261
+ '" onclick="return confirm(\'' . __( 'Are you sure?', 'woocommerce-jetpack' ) . '\')">' . __( 'Delete All Custom Statuses', 'woocommerce-jetpack' ) . '</a>' .
262
+ '</p>';
263
+ }
264
+
265
+ /**
266
+ * create_tool.
267
+ *
268
+ * @version 3.2.2
269
+ * @since 3.2.2
270
+ */
271
+ function create_tool() {
272
+ $html = '';
273
+ $html .= '<div class="wrap">';
274
+ $html .= $this->process_actions();
275
+ $html .= $this->module->get_tool_header_html( $this->id );
276
+ $html .= $this->get_custom_statuses_add_edit_table();
277
+ $html .= $this->get_custom_statuses_table();
278
+ $html .= $this->get_delete_all_custom_statuses_button();
279
+ $html .= '</div>';
280
+ echo $html;
281
+ }
282
+ }
283
+
284
+ endif;
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: algoritmika, anbinder
3
  Tags: woocommerce, booster for woocommerce, woocommerce jetpack
4
  Requires at least: 4.4
5
  Tested up to: 4.8
6
- Stable tag: 3.2.1
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -170,6 +170,39 @@ You can see the differences between versions in this [table](https://booster.io/
170
 
171
  == Changelog ==
172
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  = 3.2.1 - 30/10/2017 =
174
  * Dev - PRICES & CURRENCIES - Currency per Product - Minor code refactoring.
175
  * Dev - PRICES & CURRENCIES - Wholesale Price - Getting product directly from cart (instead of by ID) - this fixes the issue with "Product Addons" module compatibility.
3
  Tags: woocommerce, booster for woocommerce, woocommerce jetpack
4
  Requires at least: 4.4
5
  Tested up to: 4.8
6
+ Stable tag: 3.2.2
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
170
 
171
  == Changelog ==
172
 
173
+ = 3.2.2 - 12/11/2017 =
174
+ * Dev - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - "Advanced: Price Filters Priority" option added.
175
+ * Dev - PRICES & CURRENCIES - Price by User Role - "Advanced: Price Filters Priority" option added.
176
+ * Dev - PRODUCTS - Product Addons - "Text" addon type added.
177
+ * Dev - CART & CHECKOUT - Checkout Custom Fields - Template options added. Now (by default) using styling in emails and order received page.
178
+ * Dev - CART & CHECKOUT - EU VAT Number - Advanced Options - "Skip VAT Validation for Selected Countries" option added.
179
+ * Dev - CART & CHECKOUT - EU VAT Number - Display - After order table - Output restyled.
180
+ * Dev - CART & CHECKOUT - EU VAT Number - Admin settings descriptions and styling updated.
181
+ * Dev - PAYMENT GATEWAYS - Gateways by User Role - Module's main hook priority lowered (so e.g. it's now run before the "Gateways Min/Max Amounts" module).
182
+ * Fix - SHIPPING & ORDERS - Order Custom Statuses - Custom Statuses Tool - Adding "Delete" and "Edit" buttons to Booster's custom statuses only.
183
+ * Dev - SHIPPING & ORDERS - Order Custom Statuses - Custom Statuses Tool - "Delete All Custom Statuses" button added.
184
+ * Dev - SHIPPING & ORDERS - Order Custom Statuses - Custom Statuses Tool - Sanitizing slug when adding new custom status.
185
+ * Dev - SHIPPING & ORDERS - Order Custom Statuses - Default Order Status - "No changes" option added.
186
+ * Dev - SHIPPING & ORDERS - Order Custom Statuses - Major code refactoring and cleanup.
187
+ * Dev - SHIPPING & ORDERS - Order Min/Max Quantities - Min and max quantities added to quantity input on single product page (if "Per Item Quantity" is enabled).
188
+ * Dev - SHIPPING & ORDERS - Order Min/Max Quantities - "Per Item Quantity on Per Product Basis" added.
189
+ * Dev - PDF INVOICING & PACKING SLIPS - Invoices Renumerate Tool - Code cleanup. Restyling.
190
+ * Dev - PDF INVOICING & PACKING SLIPS - Numbering - "Template" option added.
191
+ * Dev - PDF INVOICING & PACKING SLIPS - Styling - Admin settings - Minor restyling.
192
+ * Dev - EMAILS & MISC. - Breadcrumbs - `hide_breadcrumbs_with_css()` - Additional identifier added.
193
+ * Dev - EMAILS & MISC. - Custom Emails - WooCommerce v3.x.x compatibility - `post_status`.
194
+ * Dev - Shortcodes - Orders - `[wcj_order_items_table]` - `wcj_order_items_table_data` filter added.
195
+ * Dev - Shortcodes - Orders - `[wcj_order_items_table]` - `sort_by_column` attribute added.
196
+ * Dev - Functions - Exchange Rates - Deprecated average exchange rates (Yahoo) calculation removed.
197
+ * Dev - Functions - Exchange Rates - Average exchange rates (Fixer.io) calculation added.
198
+ * Dev - Functions - Exchange Rates - Exchange Rates Server - "Fixer.io" server added.
199
+ * Dev - Functions - Exchange Rates - Exchange Rates Server - "Yahoo" URL updated.
200
+ * Dev - Functions - Orders - Cleanup (`wcj_get_order_statuses()`).
201
+ * Dev - Functions - Price and Currency - `wc_get_product_purchase_price()` - Converting post meta to `int` before adding (fixes PHP 7 notice).
202
+ * Fix - Functions - Users - `wcj_get_current_user_first_role()` - Code changed, so now user role is always correctly identified (i.e. with any array index).
203
+ * Dev - `WCJ_Invoice` - Default values added to `get_option()` calls.
204
+ * Dev - `WCJ_Product` - Class removed (`get_purchase_price()` function moved to `wc_get_product_purchase_price()`).
205
+
206
  = 3.2.1 - 30/10/2017 =
207
  * Dev - PRICES & CURRENCIES - Currency per Product - Minor code refactoring.
208
  * Dev - PRICES & CURRENCIES - Wholesale Price - Getting product directly from cart (instead of by ID) - this fixes the issue with "Product Addons" module compatibility.
woocommerce-jetpack.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: https://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
- Version: 3.2.1
7
  Author: Algoritmika Ltd
8
  Author URI: https://booster.io
9
  Text Domain: woocommerce-jetpack
@@ -64,7 +64,7 @@ require_once( 'includes/constants/wcj-constants.php' );
64
  * Main WC_Jetpack Class
65
  *
66
  * @class WC_Jetpack
67
- * @version 3.2.1
68
  */
69
  final class WC_Jetpack {
70
 
@@ -74,7 +74,7 @@ final class WC_Jetpack {
74
  * @var string
75
  * @since 2.4.7
76
  */
77
- public $version = '3.2.1';
78
 
79
  /**
80
  * @var WC_Jetpack The single instance of the class
@@ -249,7 +249,7 @@ final class WC_Jetpack {
249
  /**
250
  * Include required core files used in admin and on the frontend.
251
  *
252
- * @version 3.2.0
253
  */
254
  function includes() {
255
 
@@ -259,7 +259,6 @@ final class WC_Jetpack {
259
  // Classes
260
  include_once( 'includes/classes/class-wcj-module.php' );
261
  include_once( 'includes/classes/class-wcj-module-shipping-by-condition.php' );
262
- include_once( 'includes/classes/class-wcj-product.php' );
263
  include_once( 'includes/classes/class-wcj-invoice.php' );
264
  include_once( 'includes/classes/class-wcj-pdf-invoice.php' );
265
 
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: https://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
+ Version: 3.2.2
7
  Author: Algoritmika Ltd
8
  Author URI: https://booster.io
9
  Text Domain: woocommerce-jetpack
64
  * Main WC_Jetpack Class
65
  *
66
  * @class WC_Jetpack
67
+ * @version 3.2.2
68
  */
69
  final class WC_Jetpack {
70
 
74
  * @var string
75
  * @since 2.4.7
76
  */
77
+ public $version = '3.2.2';
78
 
79
  /**
80
  * @var WC_Jetpack The single instance of the class
249
  /**
250
  * Include required core files used in admin and on the frontend.
251
  *
252
+ * @version 3.2.2
253
  */
254
  function includes() {
255
 
259
  // Classes
260
  include_once( 'includes/classes/class-wcj-module.php' );
261
  include_once( 'includes/classes/class-wcj-module-shipping-by-condition.php' );
 
262
  include_once( 'includes/classes/class-wcj-invoice.php' );
263
  include_once( 'includes/classes/class-wcj-pdf-invoice.php' );
264